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

в 7:52, , рубрики: bash-скрипт, DynDNS, Песочница, метки: ,

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

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

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

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

Уже был положительный опыт использования dynamic dns сервисов (на домашнем роутере), поэтому была заведена отдельная учетка на dyndns.org.
Далее был на шлюз был установлен пакет inadyn (как один из рекомендуемых самим 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

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js