DDNS - przykład aktualizacji w PHP

DDNS – DynDns – dynamiczny DNS

W zasadzie większość z nas ma stały adres IP, najczęściej zmienia się tylko w przypadku gdy nasz router ponownie nawiązuje połączenie z usługodawcą (ISP).
W takiej sytuacji, np. w warunkach domowych, aż pragnie się wystawić na świat np. album zdjęć lub inne rzeczy, których nie chcemy umieszczać bezpośrednio na serwerach firm trzecich (w tzw. chmurze).
Tylko jak przekazać link innym? Przecież za każdym razem nie będziemy podawać czegoś w stylu http://125.130.125.2. Po pierwsze ponieważ jutro możemy mieć już inny publiczny adres IP nadany przez ISP (np. modem się zrestartował), a po drugie łatwiej zapamiętać http://home.domena.pl .

DDNS – zewnętrzni usługodawcy

Skonfigurowanie subodmeny to rzecz prosta. Pozostaje inna kwestia – jak zautomatyzować proces, aby adres home.domena.pl zawsze kierował na naszą domową maszynę? Nic prostszego – możemy wykorzystać DDNS / DynDNS / dynamiczny DNS.
Proces polega na tym, że wydzielamy z naszej domena.pl subdomenę, która ma inny TTL (czas odświeżania) i zarządzamy samą domeną oddzielnie (co też umożliwia lepszą kontrolę pod względem bezpieczeństwa).
Możemy wykorzystać darmowe serwisy oferujące usługę DDNS, gdzie dostaniemy subdomenę w ramach ich domeny. Z naszej strony pozostaje ustawić cykliczną operację (cron) na wysłanie zapytania do API celem aktualizacji wpisu DNS dla subdomeny.

Taką usługę oferuje chociażby FreeDNS. Rejestracja jest bardzo prosta, po wszystkim pozostaje nam wywołanie przekazanego URI z tokenem naszej subdomeny w naszej sieci lokalnej (router/serwer/etc):

Jeśli posiadacie własną domenę i korzystacie z gotowego panelu do zarządzania domeną to często jest możliwość skonfigurowania bezpośrednio tam DDNS. Taką usługę oferuje chociażby OVH.

DDNS – własne rozwiązanie

Ale może niektórzy z Was lubią posiadać większą kontrolę nad domeną (specyficzne rekordy) niż oferuje firma, w której opłacacie domenę. Posiadacie np. własną instancję BIND, gdzie trzymacie kilka domen (prostą konfigurację BIND opisałem w 2010 roku) i chcielibyście wykorzystać ten serwer nazw do DDNS.
Sam tak właśnie pomyślałem, gdy okazało się, że na jednym z interfejsów zewn. posiadam dość zmienną adresację.

DDNS – modyfikacja w BIND

Zacznijmy od zmiany w samym BIND. Powiedzmy, że posiadamy domenę domena.pl i jej strefa u nas wygląda następująco:

I gdy chemy dodać dodać naszą domową/lokalną subdomenę tworzymy dodatkową pozycją:

Ale w naszym przypadku dodajemy home.domena.pl z informacją, że jest zarządzana osobno:

Czyli „powiedzieliśmy”, że home.domena.pl będzie osobą strefą… Tak też zróbmy, w naszym pliku gdzie definiujemy strefy (np. etc/bind/named.conf.local) dodajemy stosowną informację:

Jak widzicie pozwalamy na modyfikację domeny (allow-update) przez serwer XXX.XXX.XXX.XX, ale również wykorzystując klucz, który nazywa się home.domena.pl. Są to 2 różne sposoby na zabezpieczenie zmian w domenie przez niepowołane osoby.
Oczywiście bezpieczniejsza opcja to poprzez klucz szyfrujący i na tym się skupimy.

Algorytm klucza możemy dobrać wg uznania, dla ułatwienia wybierzemy „krótką” wersję (HMAC-MD5). Tworzymy odpowiedni katalog na klucze i generujemy:

W wyniku otrzymamy 2 pliki, z których interesuje nas zawartość pliku *.key:

Naszym kluczem (TSIG) jest ciąg BFQTloe90QYscNMUpwptlQ== , któremu nadajemy odpowiednią nazwę, abyśmy mogli z niego korzystać.
W tym celu tworzymy plik z kluczami i informujemy o tym nasz serwer nazw. W pliku named.conf dodajemy:

i tworzymy podany plik (named.conf.tsig) z odpowiednią wartością dla klucza i informacją o rodzaju klucza:

Przeładowujemy BIND i możemy już aktualizować naszą strefę home.domena.pl uwierzytelniając się wprowadzonym kluczem lub uderzając z wprowadzonego adresu serwera

DDNS – serwer z PHP i request aktualizacyjny

Mamy przygotowane już zaplecze, pozostaje nam stworzyć fragment kodu, który będzie aktualizował strefę DNS. Jeśli mamy gdzieś dostępny serwer z PHP możemy posłużyć się takim fragmentem kodu:

Prosty, ale w pełni funkcjonalny kod update.php dostępny na GitHub.
Jak widzicie korzystamy z PIPE-ów i polecenia dostępnego w większości systemów Linux – nsupdate (łącząc się, usuwając stary rekord A, dodając nowy rekord A).
Plik wystarczy umieścić gdzieś gdzie mamy PHP, może to być localhost.

Parametr secret składa się z 2 części: nazwy klucza i samego klucza. Możemy ten ciąg znaków uzyskać następująco posiłkując się danymi z miejsca, gdzie generowaliśmy klucz:

Pozostaje nam już tylko uderzyć. Jeśli nasz router na to pozwala, lub jakiś lokalny serwer (np. NAS Synology) to tworzymy operację cykliczną (cron) z czasem ustawionym np. co 5 minut podając:

Jeśli chcecie sprawdzić czy operacja się udała, możecie skorzystać z polecenia dig:

i zweryfikować aktualnie ustawione rekord A.