Уже давно использовал сервис от компании dyndns, который позволял привязать доменное имя к динамическому ip-адресу компьютера. Удобно администрировать клиента, удобно клиенту из дома подключиться к рабочему компьютеру. Но с некоторых пор сервис начал затягивать гайки.
Сначала можно было пользоваться одним доменным именем на учетной записи бесплатно. Позже доменное имя начало сбрасываться каждый месяц — это периодически требовало усилий по восстановлению работы. Другие бесплатные сервисы не приглянулись и в какой-то момент я подписался на их платную услугу за $25 в год, что дало мне возможность использовать до 30 доменных имен.
Было неудобство — клиентская программа под Windows визуализирует все доменные имена моей учетки при настройке и любой клиент случайно или умышленно может повредить привязку чужого доменного имени. В общем, гнетет, но терпимо. На прошлой неделе пришла пора продлевать на год подписку. Цена выросла до $30, да и рубль упал к этому моменту до 60 руб за доллар. Жалко мне стало рублей и я таки решил дожать динамический DNS на своей площадке.
Исходные данные:
- windows и *nix машины с динамическими ip
- freebsd 9.3
- bind9
- apache 2.4
- php 5.3
- свой домен
Что-нужно получить:
- простую в использовании клиентскую часть
Решение:
Предположим, наш домен — MyDomain.ru. Опишем его как мастер зону в /etc/namedb/named.conf:
zone "MyDomain.ru" {
type master;
file "/etc/namedb/master/MyDomain.ru";
};
Cоответственно в /etc/namedb/master/MyDomain.ru пропишем что-нибудь типа:
$ORIGIN .
$TTL 3600 ; 1 hour
MyDomain.ru IN SOA ns1.MyDomain.ru. root.MyDomain.ru. (
2015032014 ; serial
10800 ; refresh (3 hours)
3600 ; retry (1 hour)
604800 ; expire (1 week)
86400 ; minimum (1 day)
)
NS ns1.MyDomain.ru.
NS ns2.MyDomain.ru.
A 188.120.254.163
MX 10 mail.MyDomain.ru.
MX 20 mail.MyDomain.ru.
$ORIGIN MyDomain.ru.
mail A 192.168.0.1
ns1 A 192.168.0.1
ns2 A 192.168.0.1
smtp A 192.168.0.1
www A 192.168.0.1
После выполнения:
echo named_enable="YES" >> /etc/rc.conf
echo 127.0.0.1 >> /etc/resolv.conf
/etc/rc.d/named start
Получаем работающий dns-сервер, проверяем пингом разрешение имен в адреса, если есть файерволл не забываем открыть 53 и 953 порты на вход. Ставим rdns — утилиту управления демоном named.
rndc-confgen
Ее вывод распределяем по двум файлам:
key "rndc-key" {
algorithm hmac-md5;
secret "rxeXMLrA1py6mDLhGO7dA==";
};
options {
default-key "rndc-key";
default-server 127.0.0.1;
default-port 953;
};
Помещаем в /etc/namedb/rdnc.conf, а
# key "rndc-key" {
# algorithm hmac-md5;
# secret "rxeXMLrA1py6mDLhGO7dA==";
# };
#
# controls {
# inet 127.0.0.1 port 953
# allow { 127.0.0.1; } keys { "rndc-key"; };
# };
предварительно убрав комментарий добавляем в /etc/namedb/named.conf. Если все правильно, то следующая команда должна выполнится успешно:
rndc reload
Нужно добавить немного прав юзеру, от имени которого работает named:
chown bind /etc/named/master
Создаем скрипт следующего содержания и размещаем его в /root/ddns/ddns.sh, к примеру:
#!/usr/local/bin/bash
TTL=120
SERVER=127.0.0.1
ZONE=MyDomain.ru.
HOSTNAME=$1.$ZONE
KEY="rxeXMLrA1py6mDLhGO7dA=="
new_ip_address=$2
nsupdate << EOF
server $SERVER
key rndc-key $KEY
zone $ZONE
update delete $HOSTNAME A
update add $HOSTNAME $TTL A $new_ip_address
send
EOF
Вызов его с двумя параметрами
/root/ddns/ddns test 192.168.0.2
должен добавить в нашу зону домен третьего уровня test.MyDomain.ru c адресом 192.168.0.2.
Теперь осталось как-то разрешить обращаться клиентам к этому скрипту, чтобы они могли обновлять свои имена в зоне на актуальные ip-адреса. Я решил это с помощью веб-сервера. В конфигурации апача разрешил виртуальные сервера и создал один для собственных нужд.
<VirtualHost *:80>
ServerAdmin root@MyDomain.ru
DocumentRoot "/usr/local/www/ddns"
ServerName ddns.MyDomain.ru
DirectoryIndex index.php
ErrorLog "/var/log/apache/ddns-error.log"
CustomLog "/var/log/apache/ddns-access.log" common
<Directory "/usr/local/www/ddns">
AllowOverride All
Order allow,deny
Require valid-user
Allow from all
AuthName "Who are you?"
AuthType Basic
AuthUserFile /usr/local/www/ddns/.htpasswd
</Directory>
</VirtualHost>
Основной ньюанс в том, что доступ к этому сайту возможен только с указанием имени пользователя и пароля. Учетные данные хранятся в /usr/local/www/ddns/.htpasswd, в том же каталоге размещаем php-скрипт следующего содержания:
<?php
$User = $_SERVER["REMOTE_USER"];
$IP = $_SERVER["REMOTE_ADDR"];
echo $IP;
$CMD = 'sudo /root/ddns/ddns.sh ' . $User . ' ' . $IP;
exec ($CMD);
?>
Ну и не забываем, собственно, наполнить файл учетными данными:
htpasswd -сb ./usr/local/www/ddns/htpasswd test test-password
htpasswd -b ./usr/local/www/ddns/htpasswd test1 test1-password
htpasswd -b ./usr/local/www/ddns/htpasswd test2 test2-password
Если правильно настроен sudo, нет проблем с правами доступ пользователя www, то при обращении клиента к ресурсу
http://ddns.MyDomain.ru
получаем приглашение на ввод учетных данных.
Вводим логин и пароль, получаем в браузере ответ с ip-адресом клиента. На сервере, при этом, php-скрипт по логину клиента и его ip-адресу обновляет доменное имя в dns. Еще считаю разумным добавить в настройку named для нашей зоны следующие строки:
update-policy {
grant rndc-key name test.MyDomain.ru. A;
grant rndc-key name test1.MyDomain.ru. A;
grant rndc-key name test2.MyDomain.ru. A;
};
Чтобы ключем rndc-key можно было править только разрешенные доменные имена. Еще хорошо бы общение клиента и сервера оформить через https, чтобы открытые пароли не гуляли в интернете.
Осталось только допилить клиента. Там все просто.
curl -u test:test-password http://ddns.MyDomain.ru
Утилита curl в *nix системах должна быть по-умолчанию, для Windows ее придется скачать. Оформить эту команду в bat-файл или sh-скрипт и разместить в планировщике задач или cron'е соответственно с интервалом вызова в 5 минут.
Чтобы подключить следующего клиента в эту схему, придумываем логин (домен 3-го уровня) и пароль для него. Правим клиентский скрипт и добавляем учетные данные в .htpasswd.
Автор: sergling