dynamic static dns

Сам себе DynDNS

Если по каким-то причинам вы не можете или не хотите использовать один из публичных Dynamic сервисов и у вас есть свой домен, то данная заметка может оказаться вам полезной.

Будем считать, что у нас уже есть настроенный DNS-сервер , который обслуживает зону example.com и веб-сервер с поддержкой , который будет использоваться для обновления A-записей в DNS.

Прежде всего необходимо создать ключ для динамического обновления dns-записей.

 dnssec-keygen -a HMAC-MD5 -b 512 -r /dev/urandom -n USER dyndns Kdyndns.+157+50370 ll Kdyndns.+157+50370.* -rw------- 1 root root 113 May 3 17:17 Kdyndns.+157+50370.key -rw------- 1 root root 229 May 3 17:17 Kdyndns.+157+50370.private 

В созданном файле Kdyndns.+157+50370.private нас интересует только одна строка, которая начинается с Key:

 Private-key-format: v1.3 Algorithm: 157 (HMAC_MD5) Key: PaLaoO01EvheJqQ5AfOJ9yZoumGATKhFeMdcfWFzA+VGCzURzBfhee0X4Ad54Tss7BANs562LOTQpCM52j6YGQ== Bits: AAA= Created: 20150503131756 Publish: 20150503131756 Activate: 20150503131756 

Ключ нужно добавить в файл конфигурации bind, например /etc/named.conf, и разрешить для него обновления целевой зоны.

 key "dyndns" { algorithm hmac-md5; secret "PaLaoO01EvheJqQ5AfOJ9yZoumGATKhFeMdcfWFzA+VGCzURzBfhee0X4Ad54Tss7BANs562LOTQpCM52j6YGQ=="; }; zone "example.com" { type master; file "/var/named/example.com"; allow-update { key "dyndns"; }; }; 

Так же понадобится секретный хеш для обновления DNS посредством http-запроса, который можно сгенерировать, например с помощью openssl так:

 openssl rand -hex 24 701cc7069159e9547def51b9f9c423a5660730ee3a44cdf6 

Мой пример php-скрипта для обновления DNS:

 // configuration of users and domains $udns = array( 'user' => array( 'home' => '701cc7069159e9547def51b9f9c423a5660730ee3a44cdf6' ) ); // main domain for dynamic DNS $dyndns = "example.com"; $dnskey = "PaLaoO01EvheJqQ5AfOJ9yZoumGATKhFeMdcfWFzA+VGCzURzBfhee0X4Ad54Tss7BANs562LOTQpCM52j6YGQ=="; // short sanity check for given IP function checkip($ip) { $iptupel = explode(".", $ip); foreach ($iptupel as $value) { if ($value < 0 || $value > 255) return false; } return true; } // check request data function checkreq(&$value, $default = false) { return isset($value) ? $value : $default; } // retrieve IP $ip = $_SERVER['REMOTE_ADDR']; // check for given user $user = checkreq($_REQUEST['u']); // check for given domain $subdomain = checkreq($_REQUEST['d']); // check for given secret $secret = checkreq($_REQUEST['s']); // check for needed variables if($subdomain && $ip && $user && $secret) { // short sanity check for given IP if(preg_match("/^(\d{1,3}\.){3}\d{1,3}$/", $ip) && checkip($ip) && $ip != "0.0.0.0" && $ip != "255.255.255.255") { // short sanity check for given domain if(isset($udns[$user][$subdomain]) && $udns[$user][$subdomain] == $secret) { // check for some ip if(gethostbyname($subdomain.".".$dyndns) == $ip) { echo "IP address $ip not changing for domain $subdomain"; } else { // shell escape all values $subdomain = escapeshellcmd($subdomain); $ip = escapeshellcmd($ip); // prepare command $data = '<<EOF zone $dyndns update delete $subdomain.$dyndns A update add $subdomain.$dyndns 60 A $ip send EOF'; // run DNS update exec("/usr/bin/nsupdate -y dyndns:$dnskey $data", $cmdout, $ret); // check whether DNS update was successful if ($ret != 0) { echo "Changing DNS for $subdomain.$dyndns to $ip failed with code $ret"; } } } else { echo "Domain $subdomain for $user from $ip with $subdomain was wrong"; } } } else { echo "DDNS change for $user from $ip with $subdomain failed because of missing values"; }  

Запрос скрипта со стороны клиента будет выглядеть так (безопаснее использовать https):

 wget https://dyn.rascal.su/?u=user&d=home&s=701cc7069159e9547def51b9f9c423a5660730ee3a44cdf6