QVINTVS · SCRIBET

Dynamisches DNS mit BIND selbst machen

Der Artikel befasst sich mit der Einrichtung von dynamischem DNS auf einer eigenen DNS-Infrastruktur mit BIND ohne externe Anbieter.

Allgemeines

Der Platzhirsch unter den DNS-Servern ist sicherlich der von dem Internet Systems Consortium (ISC) entwickelte Berkeley Internet Name Domain Server (BIND). Ich nutze üblicherweise lieber leichtgewichtigere Programme wie den für fast alle Zwecke ausreichenden dnsmasq, aber es gibt gewisse Konfigurationen, bei denen ein Weg an der großen, aber eben auch mächtigen Software nicht vorbei führt. Eine solche liegt etwa dann vor, wenn man dynamisches DNS einrichten möchte.

Als dynamisches DNS bezeichnet man eigentlich lediglich eine besondere Art der Konfiguration eines DNS-Servers. Dem Grunde nach unterscheiden sich dynamisch erzeugte Domains nicht von regulären; genauso wie bei einer „gewöhnlichen“ Domain wird einem DNS-Eintrag (Domain) eine IP-Adresse zugeordet, z.B. example.com 93.184.216.34 (IPv4) oder 2606:2800:220:1:248:1893:25c8:1946 (IPv6). Diese Zuordnung wird wie im DNS üblich mithilfe der A- und AAA-Records realisiert.

example.com. 85092 IN A    93.184.216.34
example.com. 85352 IN AAAA 2606:2800:220:1:248:1893:25c8:1946

Was dynamisches DNS von regulärem DNS unterscheidet ist die Art und Weise, wie der A/AAAA-Record erstellt wird. Während man im klassischen DNS-Gebrauch eine feste IP-Adresse permanent für die gewünschte Domain hinterlegt, wird bei dynamischem DNS diese Zuordnung sehr häufig geändert. Dies ist für gewöhnliche Server nicht erforderlich, betreibt man jedoch seinen eigenen Server zuhause, dann ist man oft Opfer der dynamischen Adressvergabe der großen Internet Service Providers (ISPs). Der DNS-Eintrag veraltet, d. h. zeigt auf eine falsche IP-Adresse (die jetzt womöglich ein anderer Kunde innehat) und die Nutzung ist unmöglich. Mithilfe von dynamischem DNS wird durch häufige, automatische Änderung des A/AAAA-Records sichergestellt, dass er aktuell bleibt. Tatsächlich ist die Relevanz von dynamischem DNS bei AAAA-Records, also im IPv6-Universum, eigentlich nicht vorhanden. Dynamische IP-Adressvergabe hat seine Ursache in der Knappheit der freien IPv4-Adressen und dient dazu, dass Provider mehr Kunden bedienen können, als sie eigentlich Adressen haben. Mit IPv6 stehen wieder mehr als genügend Adressen zur Verfügung (sollte man jedenfalls meinen), sodass jedermann eine ordnungsgemäße statische IPv6-Adresse erhalten sollte (tatsächlich ist die Vorstellung, man solle direkt ein /64-Netz erhalten), die ohne weiteres in einen AAAA-Record eingetragen werden kann und es so jedem (wieder) ermöglicht, daheim seine Serverdienste selbst zu betreiben. Ich konzentriere mich in diesem Artikel daher ausschließlich auf die IPv4-Umsetzung, sprich auf dynamische A-Records.

Dynamisches DNS wird heutzutage von einigen mehr oder minder seriösen Anbietern kostenlos oder gegen Bezahlung zur Verfügung gestellt. Wer sie nutzt, begibt sich damit wissentlich in die Gesellschaft von weniger ehrlichen Individuen, die dynamisches DNS als Tarninstrument für Malware-Verteilung oder illegales Fileshring ansehen; zwar ist wohl davon auszugehen, dass sich die kriminelle Nutzung dieser Dienste als Minderheit darstellt, dennoch ist es genug, um die Aufmerksamkeit gewisser Stellen auf dieselben zu lenken, wie die unrühmliche temporäre Abschaltung des Dienstes no-ip.com auf Betreiben von Microsoft zeigt. Macht man sich von einem solchen Anbieter abhängig, kann man schnell das Nachsehen haben.

Es ist aber auf erstaunlich einfache Weise möglich, dynamisches DNS selbst zu betreiben. Der Haken an der Sache: Man muss über einen öffentlich zugänglichen Server mit fester IP-Adresse disponieren können oder zumindest Beziehungen zu einem Admin eines solchen haben. Dennoch gibt es Konstellationen, in denen dynamisches DNS auch dann noch Sinn macht: etwa, wenn man private Daten lieber am langsamen Internetanschluss zuhause hostet, öffentliche Daten dagegen auf dem schnellen Webserver mit fester IP-Adresse hat. In einem solchen Fall kann man auf dem ohnehin öffentlich erreichbaren Server BIND installieren und so dynamisches DNS für den privaten Server zuhause umsetzen.

Anpassung des DNS

Damit dynamisches DNS überhaupt möglich ist, muss man über eine beliebige Domain verfügen, etwa example.com. Ich habe die Erfahrung gemacht, dass es zwar möglich ist, dynamisches DNS unmittelbar auf der 2nd-level-Domain zu betreiben, das aber mit unverhältnismäßigen Kosten verbunden ist, weil typische Domain Reseller üblicherweise wenigstens zwei unabhängige DNS-Server mit eigenen IPv4-Adressen fordern. Es ist daher sinnvoll, dynamisches DNS nur auf einer Subdomain einzusetzen, etwa dynamic.example.com, welches im Folgenden so eingestellt werden soll, dass es stets zur IPv4-Adresse des heimischen Netzwerkes auflöst.

Zunächst erschafft man eine neue DNS-Zone durch Erstellen eines NS-Records im Kontrollzentrum des eigenen DNS-Anbieters und erstellt zusätzlich feste A/AAAA-Records für den Nameserver selbst, auf dem später BIND laufen wird. Das kann etwa so aussehen (Domainnamen und IP-Adressen beispielhaft):

ns.example.com.      10000 IN A    10.10.10.1
ns.example.com.      10000 IN AAAA fe80::2
dynamic.example.com. 10000 IN NS   ns.example.com

Damit weiß die DNS-Welt darüber Bescheid, dass alle Anfragen, die die Auflösung von dynamic.example.com (oder noch tieferen Domains, etwa a.b.c.dynamic.example.com) betreffen, an den Nameserver ns.example.com zu richten sind, welcher wiederum unter den angegebenen IP-Adressen erreichbar ist.

Installation von BIND

Die Installation von BIND erfolgt mit den üblichen Methoden des lokalen Paketmanagers.

Erzeugen der Updateschlüssel

Dynamisches DNS erfolgt in einem nach RFC2136 standardisierten Verfahren, bei dem ein besonderer DNS-Befehl (UPDATE) zusammen mit einer kryptographischen Signatur an den DNS-Server (also BIND) übermittelt wird. Sowohl Server als auch Client sind im Besitz eines kryptographischen Schlüssels (sog. „shared secret“), anhand dessen sie sie Signaturen des jeweils anderen überprüfen können. Das ist zwar nicht so so sicher wie ein echtes asymmetrisches Verfahren mit öffentlichem und privaten Schlüssel, ist aber besser als nichts. Es wäre doch sehr misslich, wenn jedermann die DNS-Records neu setzen könnte und nicht bloß der Inhaber.

Das erforderliche Schlüsselpaar erzeugt man mithilfe des mit BIND mitgelieferten Programms dnssec-keygen:

$ dnssec-keygen -a hmac-sha256 -b 256 \
  -n HOST dynamic.example.com.
Kdynamic.example.com.+123+45678

Den Aufruf habe ich Abschnitt 4.5.1.1 des Benutzerhandbuchs entnommen; die Manpage lehrt, dass -a den Algorithmus festlegt, -b die Anzahl Bits des Schlüssels ist (das Benutzerhandbuch sagt, dass maximal 256 möglich sind, also habe ich das gewählt) und dass -n den Schlüsseltyp festlegt, bei dem HOST erforderlich ist, weil ja ein Schlüssel für einen bestimmten Host erzeugt werden soll und nicht etwa, wie in DNSSEC üblich, eine ganze Zone signiert werden soll. Man beachte im Übrigen den für DNS-Einträge üblichen abschließenden Punkt.

Die Datei Kdynamic.example.com.+123+45678.private enthält nunmehr den privaten Schlüssel im Feld Key:, aus dem er leicht extrahiert werden kann:

...
Key: ganzvielunleserlicherbase64kram==
...

Dieser Schlüssel wird als beiden Seiten bekanntes Geheimnis genutzt.

Konfiguration von BIND

Die Konfiguration von BIND ist einfacher, als das 224 Seiten starke und typografisch monströse (Zeilenlängen?!) Benutzerhandbuch vermuten lässt. Ich gehe hier daher davon aus, dass die grundlegende Konfiguration dem Leser bekannt ist und hebe nur diejenigen Stellen hervor, die im Rahmen der Einrichtung eines Dienstes für dynamisches DNS besonderer Würdigung bedürfen.

Die für dynamisches DNS relevante Dokumentation befindet sich in Abschnitt 4.2 des Benutzerhandbuchs für Version 9.10 von BIND. Die Datei /etc/named.conf (unter Debian /etc/bind/named.conf) wird um folgenden Inhalt ergänzt:

key dynamic.example.com. {
    algorithm "HMAC-SHA256";
    secret: "ganzvielunleserlicherbase64kram==";
};

zone dynamic.example.com. {
    type master;
    file "dynamic.example.com.zone";
    allow-update { key dynamic.example.com.; };
};

Damit wird BIND zunächst ein neuer kryptographischer Schlüssel hinzugefügt (key), bei dem als Algorithmus anzugeben ist, was zur Erzeugung an dnssec-keygen übergeben wurde. secret ist der oben erwähnte Inhalt des Feldes Key: aus der erzeugten Schlüsseldatei. Danach folgt die Zonenkonfiguration, die BIND über die neue DNS-Zone unterrichtet und es dem Inhaber des Schlüssels ermöglicht, den DNS-Befehl UPDATE auszuführen. Bei allen Namen ist darauf zu achten, dass sie einschließlich dem finalen Punkt mit dem Namen übereinstimmen, der dnssec-keygen übergeben wurde.

Schließlich ist noch eine Zonendatei für die neue Zone anzulegen, etwa /var/named/dynamic.example.com.zone:

$ORIGIN .
$TTL 200
dynamic.example.com IN SOA ns.example.com john.example.org. (
                           1
                           500
                           500
                           86400
                           500
                           )
                       NS ns.example.com.
                       A  1.2.3.4

Die Zeitintervalle mag jeder nach seinem Geschmack bemessen, aber für dynamisches DNS sind kurze Intervalle empfehlenswert, da sich ja die dynamische IP jederzeit ändern kann und diese Änderung möglichst schnell im DNS propagieren sollte. Die IP-Adresse für den A-Record kann hier noch beliebig sein; sie wird ja später eh durch das dynamische Update geändert.

Ein besondere Hinweis noch. Diese Zonendatei darf, nachdem sie einmal angelegt wurde, nicht mehr editiert werden. BIND erstellt automatisch eine Datei mit der Endung .jnl im selben Verzeichnis wie die Zonendatei (Schreibzugriff auf Verzeichnis erforderlich!), in welche die Änderungen aufgenommen werden. Wenn Korrekturen an der Zonendatei vorgenommen werden sollen, ist es äußerst ratsam, BIND vorher zu stoppen, damit der Inhalt der .jnl-Datei in die Zonendatei übernommen wird. BIND loggt Fehlermeldungen und verweigert die Auslieferung der Zone, wenn es feststellt, dass die Zonendatei nicht zur .jnl-Datei passt.

Neustart von BIND nicht vergessen.

Automatisches Aktualisieren des A-Records

Der erzeugte Schlüssel gewährt Zugriff auf die Konfiguration der gesamten Zone dynamic.example.com, effektiv benutzt wird er aber nur, um einen einzelnen A-Record für diese Domain zu setzen. Dazu dient das Tool nsupdate, das ebenfalls Teil von BIND ist. Ein Aufruf sieht so aus:

$ nsupdate -k Kdynamic.example.com.+123+45678.private <<EOF
server 10.10.10.1
update delete dynamic.example.com A
update add dynamic.example.com 200 A 1.2.3.4
send
EOF

Die Datei Kdynamic.example.com.+123+45678 ist jene, die weiter oben bereits erzeugt wurde; sie enthält das shared secret, das zu denjenigen auf dem DNS-Server passt und den Zugriff auf die Konfiguration gewährt. Die auf die Standardeingabe von nsupdate geschriebenen Befehle bewirken folgendes:

  1. Verbinde mit dem DNS-Server 10.10.10.1. Die IP ist beispielhaft; es muss sich um die IP des DNS-Servers handeln, auf dem der BIND läuft, der für die Zone dynamic.example.com zuständig ist. Wer aufgepasst hat, stellt fest, dass dies logischerweise der Server sein muss, der im dazugehörigen NS-Record angegeben ist. Um Problemen bei der DNS-Auflösung zuvorzukommen, kann man auch gleich die IP angeben, der Zielserver muss ja eh eine feste Adresse haben.

  2. Entferne den bisherigen A-Record für dynamic.example.com. Sonst werden immer mehr A-Records angesammelt, was nicht Ziel der Übung ist.

  3. Erstelle einen neuen A-Record für dynamic.example.com mit Ziel 1.2.3.4. Diese IP-Adresse muss natürlich für jeden Aufruf von nsupdate ermittelt werden.

Mit diesen Informationen lässt sich leicht ein Shellskript basteln, das den A-Record für dynamic.example.com aktuell hält. Die aktuelle eigene IP-Adresse kann man programmatisch etwa mithilfe des Befehls

$ curl http://ifconfig.me/ip

herausfinden, oder man schreibt einen entsprechenden eigenen Dienst auf dem öffentlich erreichbaren Webserver.

Ende

Der Artikel gab eine Übersicht darüber, wie man sein eigenes dynamisches DNS betreibt. Neben den bereits erwähnten Quellen sei noch dieser Blogpost erwähnt, der insbesondere die Nutzung von nsupdate erklärt, die im BIND-Benutzerhandbuch doch irgendwie zu kurz kommt.

Valete.