Залез зачем-то в справку почты для домена яндекса и заметил там Его — долгожданный API DNS.
И захотелось сделать более нативный клиент dDNS, чем всего лишь 2-х месячной давности решение через эмуляцию пользователя.
Поскольку на С делать моими силами долго получилось бы, а ни Python ни Perl я не знаю, делать будем на перле.
Итого дано:
Хочется их всех передружить.
Для начала определим IP, на который будем заменять запись:
Берём первый попавшийся IP указанного интерфейса.
И выкинем в функцию выполнение запроса к API и общие проверки ответа:
В частности, удостоверимся, что есть ответ сервера, распарсим XML и проверим, Яндекс не вернул ли API ошибку.
Теперь и основная часть:
Сим получаем список записей этого домена и обновляем все A-записи, у которых IP не тот, что мы хотим.
Вот и всё, в общем-то. Теперь осталось прописать запуск скрипта при поднятии интерфейса и можно спокойно жить дальше.
PS: под debian'ом нужно доставить, если не стоят, пакеты libcrypt-ssleay-perl, libxml-simple-perl и libwww-perl.
Обратите внимание, что API устарело в декабре 2014г.
И захотелось сделать более нативный клиент dDNS, чем всего лишь 2-х месячной давности решение через эмуляцию пользователя.
Поскольку на С делать моими силами долго получилось бы, а ни Python ни Perl я не знаю, делать будем на перле.
Итого дано:
- динамический внешний IP
- домен, делегированный на яндекс
- роутер под управлением Debian
Хочется их всех передружить.
Для начала определим IP, на который будем заменять запись:
sub getip {
(my $interface,my $ipconf) = @_;
$ipconf = defined($ipconf) ? $ipconf : '/sbin/ip';
my $res = `ip a s $interface | grep «inet »` or die(«Can't get info from ip: ».$!);
if ($res =~ /([\d]{1,3}.[\d]{1,3}.[\d]{1,3}.[\d]{1,3})/) {
return $1;
}
die(«Can't find ip»);
}
Берём первый попавшийся IP указанного интерфейса.
И выкинем в функцию выполнение запроса к API и общие проверки ответа:
sub yapi {
my $url = $_[0];
die 'Not URL in params yapi func'
unless defined($url);
my $cont = $ua->get($url);
die 'HTTP Error: ', $cont->status_line
unless $cont->is_success;
die 'Not XML, given ', $cont->content_type
unless $cont->content_type eq 'text/xml';
my $resp = XML::Simple
->new()
->XMLin( $cont->content );
die 'API error: ',$resp->{domains}->{error}
unless $resp->{domains}->{error} eq 'ok';
return ($resp->{domains}->{domain});
}
В частности, удостоверимся, что есть ответ сервера, распарсим XML и проверим, Яндекс не вернул ли API ошибку.
Теперь и основная часть:
#!/usr/bin/perl
# доменное имя
my $domain = 'example.org';
#токен авторизационный
my $token = '1bdf72e04d6b50c82a48c7e4dd38cc6920116dfd6774a9e7b32eddfe';
# новый IP, определяем по переданному первым аргументом имени интерфейса
# т.е., например, ./yaddns.pl ppp0
my $currentip = getip($ARGV[0]);
use strict;
use LWP::UserAgent;
use XML::Simple;
#use Data::Dumper; #for debug!
my $ua = LWP::UserAgent->new;
$ua->agent(«dDNS client for pdd.yandex.ru.»);
my $domainlist = yapi('https://pddimp.yandex.ru/nsapi/get_domain_records.xml?token='.$token.'&domain='.$domain)->{response}->{record};
while ( my ($record_id, $record) = each(%$domainlist) ) {
#print Dumper($record);
if ($record->{type} eq 'A' && $currentip ne $record->{content} ) {
my $update = 'https://pddimp.yandex.ru/nsapi/edit_a_record.xml?token='.$token
.'&domain='.$domain.'&subdomain='.$record->{subdomain}
.'&record_id='.$record_id.'&content='.$currentip;
print 'Обновление записи '.$record_id.' (хост '.$record->{subdomain}.")\n";
yapi($update);
}
}
Сим получаем список записей этого домена и обновляем все A-записи, у которых IP не тот, что мы хотим.
Вот и всё, в общем-то. Теперь осталось прописать запуск скрипта при поднятии интерфейса и можно спокойно жить дальше.
PS: под debian'ом нужно доставить, если не стоят, пакеты libcrypt-ssleay-perl, libxml-simple-perl и libwww-perl.
Обратите внимание, что API устарело в декабре 2014г.