dynDNS для Amazon EC2 или как автоматизировать автообновление IP на хостинге с динамическим публичным IP

от автора

Недавно встала задача развернуть виртуальный сервер Ubuntu 12.04 на Amazon EC2 для некоего сервиса и присвоить ему доменное имя в существующей доменной зоне, но как известно Amazon меняет публичный и локальный адреса после перезагрузки или выключения машины, поэтому было решено использовать bash (для *nix) и bat (для Windows) для автоматизации обновления динамического адреса для хостинга.

Такой скрипт на bash уже существует Marius Ducea Jun 1st, 2009 года. Он был немного неактуальным в плане которых команд API от Amazon, но в большинстве своём остался практически неизменным.
Всё же повторюсь как настроить работающий BIND для получения команды на синхронизацию, хотя на хабре уже есть несколько статей описывающих данный метод:
habrahabr.ru/post/101380/
habrahabr.ru/post/45921/
и много других.

Я лишь исправил некоторые команды, засунул его в автозагрузку с системой и сделал аналогичный bat-скрипт для Windows, использовав cURL и некоторые файлы от BIND.

Долго мучился почему не получается обновить зону (master и slave были на другом хостинге, работающим на Ubuntu 10.04 с установленным BIND), пришлось включить на нём логирование:

В файле /etc/bind/named.conf прописал правила для создания логов, которые будут записаны в папку в /var/log/named/

logging {     channel bind_log {     file "/var/log/named/named.log";     print-time yes;     print-category yes;     print-severity yes;     };     channel update_debug {     file "/var/log/named/update-debug.log";     severity debug 3;     print-time yes;     print-category yes;     print-severity yes;     };     channel security_info {     file "/var/log/named/security-info.log";     severity info;     print-time yes;     print-category yes;     print-severity yes;     };     category default { bind_log;};     category xfer-in { bind_log;};     category xfer-out { bind_log;};     category update { update_debug;};     category security { security_info;}; }; 

После

/etc/init.d/bind9 restart 

логи появились и можно было попробовать обновить зону скриптом, который был немного модифицирован, но вначале надо было создать ключи, я использовал 512 бит:

dnssec-keygen -a HMAC-MD5 -b 512 -r /dev/urandom -n USER example.com 

Получили 2 файла:

Kexample.com.+157+10000.key Kexample.com.+157+10000.private 

В скрипте необходимо указать путь к полученному private — ключу:

#!/bin/bash  #Путь к приватному ключевому файлу DNS_KEY="/etc/bind/key/Kexample.com.+157+10000.private" #Имя домена DOMAIN=example.com  #Имя поддомена статически HOSTNAME=site1 #Раскомментировать нижние 2 строки, если надо использовать динамическое имя (возможны ошибки при внесении записи в DNS) #USER_DATA=`/usr/bin/curl -s http://169.254.169.254/latest/meta-data/local-hostname` #HOSTNAME=`echo $USER_DATA` #Установить имя до следующей перезагрузки hostname $HOSTNAME.$DOMAIN echo Поддомен и домен: $HOSTNAME.$DOMAIN  PUBIP=`/usr/bin/curl -s http://169.254.169.254/latest/meta-data/public-ipv4` echo Публичный адрес: $PUBIP cat<<EOF | /usr/bin/nsupdate -k $DNS_KEY -v server ns1.$DOMAIN zone $DOMAIN update delete $HOSTNAME.$DOMAIN A update add $HOSTNAME.$DOMAIN 60 A $PUBIP send EOF  LOCIP=`/usr/bin/curl -s http://169.254.169.254/latest/meta-data/local-ipv4` echo Локальный адрес: $LOCIP cat<<EOF | /usr/bin/nsupdate -k $DNS_KEY -v server ns1.$DOMAIN zone $DOMAIN update delete local.$HOSTNAME.$DOMAIN A update add local.$HOSTNAME.$DOMAIN 60 A $LOCIP send EOF 

, а в DNS сервере указать содержимое публичного ключа в файле подгружаемых зон (у меня это named.conf.local):

key example.com. {         algorithm HMAC-MD5;         secret "ynl7o+JFPekH4iUaptw7z12xLhkUBJTmqbmTYa1xe+Gpt26HVaff+qQW hlmWcvAUeYdg19B+M4YeFrfhAvlcLQ=="; }; zone "example.com" {         type master;         file "/etc/bind/master/example.com";         allow-update { key example.com.; };         allow-query { any; };  }; 

Содержимое публичного ключа:

example.com. IN KEY 0 3 157 ynl7o+JFPekH4iUaptw7z12xLhkUBJTmqbmTYa1xe+Gpt26HVaff+qQW hlmWcvAUeYdg19B+M4YeFrfhAvlcLQ== 

Перезагружаем на хостинге с master/slave–записьсью DNS сервер и смотрим логи при попытке обновить зону полученным скриптом на хостинге Amazon.

Был получен отлуп:
named.log

26-Jan-2013 22:53:27.780 update-security: info: client 192.168.254.1#58180: signer "example.com" approved 26-Jan-2013 22:53:27.782 general: error: /etc/bind/master/example.com.jnl: create: permission denied 26-Jan-2013 22:53:27.881 update-security: info: client 192.168.254.1#52062: signer "example.com" approved 26-Jan-2013 22:53:27.883 general: error: /etc/bind/master/example.com.jnl: create: permission denied 

update-debug.log

26-Jan-2013 22:53:27.780 update: info: client 192.168.254.1#58180: updating zone 'example.com/IN': deleting rrset at 'flussonic.example.com' A 26-Jan-2013 22:53:27.781 update: info: client 192.168.254.1#58180: updating zone 'example.com/IN': adding an RR at 'flussonic.example.com' A 26-Jan-2013 22:53:27.781 update: debug 3: client 192.168.254.1#58180: updating zone 'example.com/IN': checking for NSEC3PARAM changes 26-Jan-2013 22:53:27.782 update: info: client 192.168.254.1#58180: updating zone 'example.com/IN': error: journal open failed: unexpected error 26-Jan-2013 22:53:27.882 update: info: client 192.168.254.1#52062: updating zone 'example.com/IN': deleting rrset at 'local.flussonic.example.com' A 26-Jan-2013 22:53:27.882 update: info: client 192.168.254.1#52062: updating zone 'example.com/IN': adding an RR at 'local.flussonic.example.com' A 26-Jan-2013 22:53:27.882 update: debug 3: client 192.168.254.1#52062: updating zone 'example.com/IN': checking for NSEC3PARAM changes 26-Jan-2013 22:53:27.883 update: info: client 192.168.254.1#52062: updating zone 'example.com/IN': error: journal open failed: unexpected error 

в логах было написано что нет разрешения за запись, хотя на файлах и папках стояло разрешение записи для пользователя и группы bind.
Поиски в интернете гласили что надо поправить строчку в /etc/apparmor.d/usr.sbin.named
c

/etc/bind/** r, 

на

/etc/bind/** rw, 

, но это означает уменьшить безопасть зон, расположенных в этой директории, но я как обычно полагаюсь на авось.
Далее надо перезагрузить разрешения и сам BIND

/etc/init.d/apparmor restart /etc/init.d/bind9 restart 

После очередного рестарта сервиса на DNS хостинге ошибка исчезла и зона благополучно обновилась, но все закомментированные в ней данные были утеряны, т.к. bind «навёл порядок» в записях и поудалял лишнее, поэтому следует сделать копию всех зон.

Так же следовало данный скрипт сделать автозапускаемым, т.к. после включения виртуалки неудобно заходить через ssh на ужасное имя ec2-55-240-2-74.compute-1.amazonaws.com (постоянно меняется) и руками его запускать что бы обновить зону.
Для этого я сделал его исполняемым и скопировал в /etc/init.d/

chmod +x ec2-hostname.sh cp ec2-hostname.sh /etc/init.d/ update-rc.d ec2-hostname.sh defaults 

Для Windows оказалось всё намного проще:

@echo off Setlocal enabledelayedexpansion rem Путь к приватному ключевому файлу set DNS_KEY="Kexample.com.+157+10000.private" rem Имя домена set DOMAIN=example.com rem Имя поддомена set HOSTNAME=site1 echo Поддомен и домен: %HOSTNAME%.%DOMAIN%  for /F "Delims=" %%P In ('curl -s http://169.254.169.254/latest/meta-data/public-ipv4') Do Set PUBIP=%%~P echo Публичный адрес: %PUBIP% ( @echo server ns1.%DOMAIN% @echo zone %DOMAIN% @echo update delete %HOSTNAME%.%DOMAIN% A @echo update add %HOSTNAME%.%DOMAIN% 60 A %PUBIP% @echo send ) | nsupdate -k %DNS_KEY% -v   for /F "Delims=" %%L In ('curl -s http://169.254.169.254/latest/meta-data/local-ipv4') Do Set LOCIP=%%~L echo Локальный адрес: %LOCIP% ( @echo server ns1.%DOMAIN% @echo zone %DOMAIN% @echo update delete local.%HOSTNAME%.%DOMAIN% A @echo update add local.%HOSTNAME%.%DOMAIN% 60 A %LOCIP% @echo send ) | nsupdate -k %DNS_KEY% -v   :eof 

И поместить его в шедулер с запуском при старте системы.
Последнюю версию cURL брал здесь: www.paehl.com/open_source/
BIND: www.isc.org/software/bind
От BIND нужны только файлы:

libisc.dll liblwres.dll libisccfg.dll libbind9.dll libeay32.dll libdns.dll libxml2.dll nsupdate.exe 

Их можно положить рядом со скриптом или же закинуть в %WINDIR%\system32

Вывод из всего этого:
Хоть я и выполнил данное задание, безопасть DNS сервера стала ещё меньше, т.к. добавилась ещё одна уязвимость и риск потерять правильно настроенную зону.
Прежде чем повторять написанное здесь, следует чётко понимать что же надо получить, сделать копию всех критически важных и изменяемых объектов, надо быть уверенным что в случае какого-либо сбоя можно получить доступ к машине и исправить ситуацию.
За последствия я не отвечаю, т.к. сам не уверен в её правильности.

P.S.
Прошу прощения за такой сумбурный текст, и возможные ошибки.

ссылка на оригинал статьи http://habrahabr.ru/post/167349/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *