Perl
7 October 2014

Самодельный Dynamic DNS

Статья о том, как за несколько минут своими руками сделать Dynamic DNS с помощью Perl, Yandex DNS API и роутера D-Link.

Многие роутеры D-Link поддерживают встроенную функцию Dynamic DNS.
К сожалению, бесплатно доступны лишь домены вида example.dlinkddns.com.

Есть также очень удобное DNS API от Яндекса.

Этим сочетанием мы и воспользуемся.

Для начала нужно подключить домен к сервису Яндекса — pdd.yandex.ru/domains_add.
Далее получаем для нашего домена токен, для этого нужно перейти по ссылке вида:
pddimp.yandex.ru/get_token.xml?domain_name=example-site.ru
(example-site.ru — имя домена).

Получили токен — нечто вроде «gjkgwrth34wjh45kj2th234jkht34234lkj5».
Далее — переходим по ссылке вида:
pddimp.yandex.ru/nsapi/get_domain_records.xml?token=gjkgwrth34wjh45kj2th234jkht34234lkj5&domain=example-site.ru
Получаем список записей DNS-зоны нашего домена в формате XML, нечто вроде следующего:

<page>
  <domains>
    <domain>
      <name>example-site.ru</name>
      <response>
        <record domain="example-site.ru" priority="" ttl="21600" subdomain="@" type="A" id="23232301">3.5.7.9</record>
        <record domain="www.example-site.ru" priority="" ttl="21600" subdomain="www" type="A" id="23232302">3.5.7.9</record>
      </response>
    </domain>
    <error>ok</error>
  </domains>
</page>


Из этого отклика нам нужны аттрибуты id тэгов record.

Используя все это, можем написать perl-скрипт для обновления IP.

use LWP::UserAgent;

my $hostout = `host example.dlinkddns.com`; //адрес нашего роутера

if ($hostout =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/) {
  my $ip = "$1.$2.$3.$4";

   #Добавлено:
  open (FILE,"my_ip.txt");
  my @lines = <FILE>;
  $old_ip = $lines[0]; #Считываем IP из файла
  $old_ip =~ s/^\s+|\s+$//g; #trim
  close(FILE);
  if ($old_ip eq $ip) {
    die "IP not changed"; # Выходим из скрипта, если IP не изменился
  }
  open (FILE,">my_ip.txt");
  print FILE $ip; # Записываем в файл новый IP
  close(FILE);

  my $token = "gjkgwrth34wjh45kj2th234jkht34234lkj5";
  my $domain00 = "example-site.ru";
  my $id00 = "23232301";
  my $subdomain01 = "www";
  my $id01 = "23232302";
  my $url00 ="https://pddimp.yandex.ru/nsapi/edit_a_record.xml?token=$token&domain=$domain00&record_id=$id00&content=$ip";
  my $url01 ="https://pddimp.yandex.ru/nsapi/edit_a_record.xml?token=$token&domain=$domain00&subdomain=$subdomain01&record_id=$id01&content=$ip";

  my $ua = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 } );

  my $response = $ua->get($url00);   
  if ( $response->is_success ) {
    print $response->decoded_content;
  } else {
    die $response->status_line;
  }

  my $response = $ua->get($url01);
  if ( $response->is_success ) {
    print $response->decoded_content;
  } else {
    die $response->status_line;
  }
}


Осталось только прописать в /etc/crontab строчку вроде
*/5 * * * * root perl /root/update_my_ip.pl
(для обновления каждые 5 минут, update_my_ip.pl — имя нашего скрипта).

+5
30k 111
Comments 28