Pull to refresh

Еще один вариант динамического DNS на своей площадке или как я отказался от dyndns

Reading time 4 min
Views 32K
Уже давно использовал сервис от компании 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
/etc/rc.d/named start


Получаем работающий dns-сервер, проверяем пингом разрешение имен в адреса, если есть файерволл не забываем открыть 53 и 953 порты на вход. Настраиваем rndc — утилиту управления демоном named.

rndc-confgen

Ее вывод распределяем по двум файлам:

key "rndc-key" {
    algorithm hmac-md5;
    secret "rxeXMLrA\1py6mDLhGO7dA==";
};

options {
    default-key "rndc-key";
    default-server 127.0.0.1;
    default-port 953;
};


Помещаем в /etc/namedb/rndc.conf, а

# key "rndc-key" {
#       algorithm hmac-md5;
#       secret "rxeXMLrA\1py6mDLhGO7dA==";
# };
#
# controls {
#       inet 127.0.0.1 port 953
#       allow { 127.0.0.1; } keys { "rndc-key"; };
# };

предварительно убрав комментарий добавляем в /etc/namedb/named.conf. Если все правильно, то следующая команда должна выполнится успешно:

rndc reload


Можно посмотреть статус
rndc status

Можно почитать man по rndc

Нужно добавить немного прав юзеру, от имени которого работает named:

chown bind /etc/named/master

Создаем пользователя ddns (c домашним каталогом /home/ddns), от имени которого будет работать скрипт обновления записи dns-сервера.
Создаем скрипт следующего содержания и размещаем его в /home/ddns/ddns.sh, к примеру:

#!/usr/local/bin/bash
TTL=120
SERVER=127.0.0.1
ZONE=MyDomain.ru.
HOSTNAME=$1.$ZONE
KEY="rxeXMLrA\1py6mDLhGO7dA=="
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


Не забывает
chown ddns:ddns /home/ddns/ddns.sh 
chmod 700 /home/ddns/ddns.sh 

Вызов его с двумя параметрами

/home/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 -u ddns /home/ddns/ddns.sh ' . $User . ' ' . $IP;
exec ($CMD);
?>


К сожалению у меня не получилось запустить из php bash-скрипт напрямую, полагаю это вызвано настройками безопасности пользователя www, от имени которого работает служба веб-сервера. Поэтому использую sudo от имени пользователя ddns (обычный пользователь, в домашнем каталоге которого лежит сам скрипт). Вот содержимаое файла /usr/local/etc/sudoers для этого:

www ALL=(ddns) NOPASSWD: /home/ddns/ddns.sh

Ну и не забываем, собственно, наполнить файл учетными данными:

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.
Tags:
Hubs:
+15
Comments 34
Comments Comments 34

Articles