2021-04-23 18:06:42

Dynamic DNS на Яндексе силами MikroTik RouterOS

DNS Mikrotik

Mikrotik

Все началось с того, что мне захотелось слушать музыку в машине, но надоело писать файлы на флекшки. Варианты всяких источников из интернета были так же быстро отметены, поскольку требуют денег или добавляют платные сервисы на мобильник, запретить которые оператор не в состоянии (оно и понятно, это их доход). После очередной ругани с оператором, я забил на все приложения вида "радио бесплатно и без рекламы" и решил поднять свое радио, благо музыки на домашнем сервере хватает.

Не буду описывать как поднять Icecast и вещать в интернет mp3-шки, и пробросить порт на микротике, это все гуглится и делается без бубнов. С одним лишь замечанием, многие провайдеры, среди которых билайн, блокируют все входящие на порты меньше 1000, поэтому придется жить на четырехзначном порту.

Вишенкой на торте всей этой конструкции является заворачивание своего динамического IP в доменное имя. Существует много dDNS провайдеров, в том числе встроенные в роутеры, но раз уж у меня свой домен, то радио должно быть тоже на нем. Я использую бесплатный Яндекс DNS aka почта для домена. У этого сервиса есть АПИ, плюс обновления в ДНС проходят достаточно быстро, этого вполне достаточно для моих целей.


В домашней сети я использую роутер Mikrotik, это действительно стоящая штука для тех кто хочет не просто интернет в телефончике, а нормальную сеть дома. Да, в настройке он сложнее чем большинство роутеров, но обладает несравнимо большими возможностями. Это реально стоит того, чтоб хоть немножко начать разбираться, ну а для тех кому знакомо администрирование сетей на юникс-подобных, многое будет привычно и удобно.

За основу была взята статья Делаем dDNS-клиент для DNS Яндекса на MikrotikOS и RouterOS (MikroTik) Yandex DNS subdomain A record updater. Все можно было бы просто скопипастить, если б янедкс не обновил апи, и немного не поменял формат выдачи. Так же я разгрузил логику получения идентификатора записи по имени домена, это достаточно сделать один раз руками и сократить львиную долю скрипта. После некоторых экспериментов получился вот такой скрипт:

# To use the script, add it to the scheduler and set interval 5 minutes.
# /system script run UpdateYaDNS.rsc

# get token
# https://pddimp.yandex.ru/get_token.xml?domain_name=...
# get record id
# https://pddimp.yandex.ru/nsapi/get_domain_records.xml?token=...

:local apiToken "...";
:local recordId "...";
:local ttl "3600";
:local domain "...";
:local interfaceName "...";

:local currentInterfaceIp [ :tostr [ /ip address get [/ip address find interface=$interfaceName] address ] ];
:set currentInterfaceIp [ :pick $currentInterfaceIp 0 [ :find $currentInterfaceIp "/" ] ];
:if ([ :len $currentInterfaceIp ] = 0 ) do= {
    :log info "[Ya.DNS] No IP address is assigned to the interface '$interfaceName'.";
    :error "[Ya.DNS] No IP address is assigned to the interface '$interfaceName'.";
}

:local subdomain [ :pick $domain 0 [ :find $domain "." ] ];
:local externalIp [ /resolve $domain ];
:if ($currentInterfaceIp != $externalIp) do={
    :put "[Ya.DNS] IP $externalIp changed to $currentInterfaceIp";
} else={
    :error "[Ya.DNS] IP is not changed";
}

:local result [ /tool fetch \
    mode=https \
    url=( "https://pddimp.yandex.ru/nsapi/edit_a_record.xml?token=" . $apiToken . "&record_id=" . $recordId . "&content=" . $currentInterfaceIp . "&ttl=" . $ttl . "&subdomain=" . $subdomain ) \
    as-value output=user ];

:local data ($result->"data");
:local error [ :pick $data ([ :find $data "" ] + 7) [ :find $data "" ] ];
:put $error;
:if ($error != "ok") do={
    :log warning "[Ya.DNS] Unable to update record $recordId ($error)";
    :error "[Ya.DNS] Unable to update record $recordId ($error)";
}

:log info "[Ya.DNS] Successfuly updated A record $recordId ($currentInterfaceIp)";

Согласно комментариям в шапке скрипта идем и получаем токен по имени домена (для этого нужно быть залогиненым на яндексе), затем получаем ид записи с помощью токена. Подставляем эти данные плюс название интерфейса со внешним адресом и полное имя домена в переменные. В блоке Policy отмечаем "ftp" и "read", и добавляем скрипт на свой роутер под именем UpdateYaDNS.rsc, далее ставим его в планировщик раз в 5 минут или как вам больше нравится, не забудьте добавить "test" в Policy у записи в планировщике. Результат действий можно будет увидеть в логах.