- PVSM.RU - https://www.pvsm.ru -

Re: Узнать белый IP-адрес роутера с сервера, который за NAT-ом

Доброго времени суток Хабр.

Не имея возможности отвечать на вопросы из раздела QA, решил сделать небольшой пост с ответом на этот вопрос.
Мое решение несколько шире, чем вопрос, и надеюсь оно кому-то пригодиться еще.

Небольшая предыстория.
В свое время устроился на работу приходящим админом в небольшую организацию. Интернет раздавался через один компьютер (назовем его шлюзом), который бриджем устанавливал соединение по ADSL с динамическим белым IP.

Так как постоянно я не находился в офисе, для оперативного решения мелких вопросов нужен был удаленный доступ в локальную сеть организации. После избавления на шлюзе винды (да там была Windows XP и Kerio Winroute Firewall) и установки CentOS 6, задался вопросом о постоянной возможности коннекта к шлюзу.

Уже был положительный опыт использования dynamic dns сервисов (на домашнем роутере), поэтому была заведена отдельная учетка на dyndns.org.
Далее был на шлюз был установлен пакет inadyn [1] (как один из рекомендуемых самим dyndns.org).

После этого были написаны 2 bash скрипта. Оба запускаются по крону, первый каждые 5 минут, второй — каждую неделю. Сделано это было по следующей причине.
Если каждые 5 минут отправлять на сервер свой неизменный IP, тогда после определенного количества попыток dyndns.org просто заблокирует четную запись, и разблокировать снова можно, только зайдя в учетную запись. Поэтому первый скрипт перед отправкой своего IP на dyndns.org сначала его проверяет — отличается ли текущий реальный IP от того, который выдает сам сервис dyndns.org на доменное имя.
Второй скрипт нужен, чтобы сервис dyndns.org не забывал об этом аккаунте, т.к. опять же в бесплатном режиме если к сервису dyndns.org долго не обращаешься — то опять идет блокировка аккаунта. Поэтому второй скрипт отправляет IP всегда, даже если он не изменился.

Собственно теперь сами скрипты.
Первый ipupdate:

#!/bin/sh
logger -t ipupdate "UPDATING IP START"

# HOSTNAME is your DynDNS hostname
HOST2=my-remote-server.dyndns.org
HOST3=my-remote-server-other.dyndns.org


# NSLOOKUP is the current DNS entry for your DynDNS hostname
OLD_IP2=`/usr/bin/nslookup -sil $HOST2 | tail -2 | head -1 | cut -d" " -f2 | grep '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'`
if [ "$OLD_IP2" = "" ]  ; then
	logger -t ipupdate "Not entry IP for $HOST2. Second empty..."
	OLD_IP2=`ping $HOST2 -c 1 | head -1 | cut -d" " -f3 | sed 's/(//' | sed 's/)//' | grep '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'`
fi
if [ "$OLD_IP2" = "" ]  ; then
	logger -t ipupdate "Not entry IP for $HOST2. Second empty: FAILED"
fi

OLD_IP3=`/usr/bin/nslookup -sil $HOST3 | tail -2 | head -1 | cut -d" " -f2 | grep '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'`
if [ "$OLD_IP3" = "" ]  ; then
	logger -t ipupdate "Not entry IP for $HOST3. Second empty..."
	OLD_IP3=`ping $HOST3 -c 1 | head -1 | cut -d" " -f3 | sed 's/(//' | sed 's/)//' | grep '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'`
fi
if [ "$OLD_IP3" = "" ]  ; then
	logger -t ipupdate "Not entry IP for $HOST1. Second empty: FAILED."
fi

if [ "$OLD_IP2" = "" ] && [ "$OLD_IP3" = "" ] ; then
	logger -t ipupdate "CHECKING INTENAL IP FAILED"
	logger -t ipupdate "EXIT"
	exit
fi

# Services for check external ip
CHECK_IP0='ifconfig.me/ip'
CHECK_IP1='http://checkip.dyndns.com'
CHECK_IP2='http://2ip.ru'
CHECK_IP3='http://www.netins.net/dialup/tools/my_ip.shtml'

logger -t ipupdate "$HOST2 has IP: $OLD_IP2"
logger -t ipupdate "$HOST3 has IP: $OLD_IP3"

logger -t ipupdate "Check external IP throw $CHECK_IP0"
CURRENT_IP=`/usr/bin/curl $CHECK_IP0 | grep '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'`

if [ "$CURRENT_IP" = "" ]; then
	logger -t ipupdate "Checking external IP throw $CHECK_IP0 FAILED"
	logger -t ipupdate "Check external IP throw $CHECK_IP2"
	CURRENT_IP=`/usr/bin/lynx -dump $CHECK_IP1 | awk '/Current IP Address:/ { print $4; }' | grep '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'`
fi

if [ "$CURRENT_IP" = "" ]; then
	logger -t ipupdate "Checking external IP throw $CHECK_IP1 FAILED"
	logger -t ipupdate "Check external IP throw $CHECK_IP2"
	CURRENT_IP=`/usr/bin/lynx -dump $CHECK_IP2 | awk '/Ваш IP адрес:/ { print $4; }' | grep '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'`
fi

if [ "$CURRENT_IP" = "" ]; then
	logger -t ipupdate "Checking external IP throw $CHECK_IP2 FAILED"
	logger -t ipupdate "Check external IP throw $CHECK_IP3"
	CURRENT_IP=`/usr/bin/lynx -dump $CHECK_IP3 | grep -A2 "Your current IP Address is:" | tail -n1 | tr -d ' '|sed '/^$/d'| sed 's/^ *//g' | grep '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'`
fi

if [ "$CURRENT_IP" = "unknown" ] || [ "$CURRENT_IP" = "" ] ; then
	logger -t ipupdate "Checking external IP throw $CHECK_IP3 FAILED"
	logger -t ipupdate "CHECKING EXTERNAL IP FAILED"
	logger -t ipupdate "EXIT"
	exit
fi
logger -t ipupdate "Real IP: $CURRENT_IP"

if [ "$OLD_IP2" != "$CURRENT_IP" ] || [ "$OLD_IP3" != "$CURRENT_IP" ] ; then
	logger -t ipupdate "IP need to update"
	if [ "$OLD_IP2" != "$CURRENT_IP" ] ; then
		inadyn --input_file /etc/inadyn/remote1.conf
	fi
	if [ "$OLD_IP3" != "$CURRENT_IP" ] ; then
		inadyn --input_file /etc/inadyn/remote2.conf
	fi

	logger -t ipupdate "sleeping for 30 sec"
	sleep 30

	logger -t ipupdate "daemon for updating has stoped"
	killall inadyn

	# Flush local DNS cache of $HOSTNAME
	/sbin/service named restart
	else
	logger -t ipupdate "Current IP is actual"
fi
logger -t ipupdate "UPDATING IP FINISHED"
exit

my-remote-server.dyndns.org и my-remote-server-other.dyndns.org — это примеры алиасов с разных учеток. Мне нужно больше 2х ДНС-имен, поэтому зарегистрировал 2 учетки. Проверка IP адресов идет по все ДНС-именам.
remote1.conf и remote2.conf — конфиги разных учеток для dyndns.org.
logger — записывает в стандартный лог фразу, можно убрать — на работу не скажется

Второй ipupdWeek:

#!/bin/sh
logger -t ipupdWeek "WEEK UPDATING IP START"

# script name of updating IP
script='ipupdate'

# check for running of script of update IP
scriptRunning=`/bin/ps aux | grep $script | grep -v 'grep'`

if [ "$scriptRunning" = "" ]; then
	logger -t ipupdWeek "Script of updating IP IS NOT running"
	echo "Not running"
else
	logger -t ipupdWeek "Script of updating IP IS RUNNING, killall it"
	killall $script
fi

logger -t ipupdWeek "Start inadyn to update all IP"
inadyn --input_file /etc/inadyn/remote1.conf
inadyn --input_file /etc/inadyn/remote2.conf

logger -t ipupdWeek "Sleeping 10 sec"
sleep 10

logger -t ipupdWeek "Stop inadyn"
killall inadyn
logger -t ipupdWeek "WEEK UPDATING IP STOP"
exit

Здесь думаю все понятно.

Вот эти 2 скрипта с минимальными изменениями (добавил еще сервисы для проверки текущего IP) уже работают больше 2х лет. Перебои с электроэнергией и интернетом не страшны — после установки интернет-соединения в течение 5 минут (можно изменить в кроне) я снова буду иметь возможность удаленно подключиться.

P.S. Не претендую на что-то оригинальное, но в свое время пришлось потратить время на эти скрипты, надеюсь этот пост кому-то поможет это время сэкономить.

P.P.S. Чтобы вообще не заморачиваться со всем этим — модем в режим роутера (само собой проброс портов) и настроить dyndns в самом модеме.
На тот момент, когда все это делал — модем загибался от работы в режиме роутера. Сейчас с новым модемом — пока не вижу смысла что-то менять, ибо «работает — ради бога не трогай» (с).

Автор: iLexx_13

Источник [2]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/pesochnitsa/33273

Ссылки в тексте:

[1] inadyn: http://www.inatech.eu/inadyn/

[2] Источник: http://habrahabr.ru/post/178327/