LINUXMAKER, OpenSource, Tutorials

Dynamisches DNS (DDNS) auf Debian Linux

Dadurch, dass Internetprovider in erster Linie dynamische IP-Adressen vergeben, die sich alle 24 Stunden erneuern, können heimische Computer nur bei Wissen dieser dynamischen IP-Adresse über das Internet erreichbar sein. Das ist ziemlich umständlich, vor allem wenn man VPN-Leitungen zu einem anderen Computer im Internet nutzen will

Um übers Internet auf den heimischen PC oder das Heimnetz zugreifen zu können, müssen diese also unter einer festen Internet-Adresse erreichbar sein. Und hier stellt das Dynamische DNS  (DDNS) eine Technik zur Verfügung, um Domains in einem Domain Name System (DNS) dynamisch zu aktualisieren. Damit wird für einen Computer nach dem Wechsel seiner IP-Adresse automatisch und schnell der dazugehörige Domaineintrag auf dem verantwortlichen DNS-Server geändert. So ist der Computer immer unter demselben Domainnamen erreichbar, auch wenn die aktuelle IP-Adresse für den Nutzer wie erwähnt unbekannt ist.

Wie man einen solchen DDNS-Server auf Linux einrichtet, soll hier erklärt werden.

Voraussetzungen

Voraussetzung ist allerdings ein bereits funktionierender DNS-Server mit Bind9. Des weiteren gehen wir davon aus, dass eine Zone example.org bereits existiert. Unter Debian werden neben dem deb-Paket 'bind9' auch die Pakete 'bind9-host', 'bind9utils' und 'dnsutils' benötigt.

Keys erstellen für die Authentifizerung

Mit dnssec-keygen wird ein Schlüssel erstellt, mit dem man sich später am DNS-Server authentifizieren kann.

# dnssec-keygen -a hmac-md5 -b 256 -n HOST dyndns.example.org

Zu den benutzten Optionen des Programmes soviel, dass der Parameter -a den Algorithmus festlegt, -b die Bit-Anzahl des Schlüssels bestimmt und -n den Schlüsseltyp angibt. Für die Bit-Anzahl verwenden wir hier die höchstmögliche Zahl laut Manpage und da wir nicht eine ganze Zone, sondern nur für einen bestimmten Host den Schlüssel erzeugen wollen, nehmen wir den Parameter "HOST".

Man findet dann nach dem Generieren in dem aktuellen Verzeichnis folgende zwei Dateien:

# -rw------- 1 root root  82 Apr 10 10:48 Kdyndns.example.org.+163+46242.key
# -rw------- 1 root root 188 Apr 10 10:48 Kdyndns.example.org.+163+46242.private

Die Inhalte beider Dateien sehen in etwa so aus und ist base64 kodiert

Private-key-format: v1.3
Algorithm: 163 (HMAC_MD5)
Key: LMbhYz5nZbP1c6OWTEJJ9sMKDQCvPy3kUO4y2aa+9cI=
Bits: AAA=
Created: 20140410084801
Publish: 20140410084801
Activate: 20140410084801

und

dyndns.example.org. IN KEY 512 3 163 LMbhYz5nZbP1c6OWTEJJ9sMKDQCvPy3kUO4y2aa+9cI=

Den Private-Schlüssel wird man später auf dem eigentlichen Client hinter der dynamischen IP-Adresse benötigen.

Erweiterte Konfiguration von Bind9

Damit jetzt die entsprechende Zonen-Datei auf dem Nameserver auch verändert werden darf, müssen die Voraussetzungen dazu geschaffen werden. Zunächst muss die Authentifizierung für die besagte Zone generiert werden. Somit erzeugen wir eine Schlüsseldatei namens 'dyndns.example.org-key.key'.

# awk '/Key/{ print "key foobar.example.org {\n algorithm HMAC-SHA256;\n secret \"", $2, "\";\n};"  }' Kdyndns.example.org.+163+46242.private | tee -a /etc/bind/named.keys

Die Datei /etc/bind/named.keys sollte dann einen ähnlichen Inhalt wie hier besitzen und kann mehrere Key-Einträge beherbergen

key dyndns.example.org {
  algorithm hmac-md5;
  secret " LMbhYz5nZbP1c6OWTEJJ9sMKDQCvPy3kUO4y2aa+9cI= ";
};

Nachdem diese Datei nur vom User bind gelesen werden und dieser Schreibberechtigungen auf dem Verzeichnis /etc/bind benötig, wird Folgendes notwendig

# chmod 600 /etc/bind/named.keys
# chown -R bind.bind /etc/bind

Anschließend wird die Authentifizierung vor den Zonendefinitionen in /etc/bind/name.conf.local bekannt gemacht.

include "/etc/bind/named.keys";

Berechtigungen für den A-Record in der Zonendatei

Ziel ist es, dem Benutzer 'bind' die Erlaubnis, den A-Record in der betreffenden Zonendatei ändern zu können,  zu erteilen. Das wird durch die Option 'update-policy' in der jeweiligen Zonendefinition ermöglicht. Konkret also so

zone "example.org" {
  type master;
  file "/var/lib/bind/db.example.org";
  update-policy {
    grant dyndns.example.org name dyndns.example.org. A;
  };
};

Wichtig ist hier, dass der erste Parameter von 'grant' in der Update-Policy der Schlüsselname ist, wie er in der eben erzeugten Schlüsseldatei festgehalten ist. Damit wird authentifiziert, dass der Key dyndns.example.org den A-Record von dyndns.example.org in dieser Zonendatei ändern darf. Ferner ist es sehr wichtig, dass der Hostname mit einem einzelnen Punkt . abschließt.

Zuletzt wird ein Neustart des Bind-Services notwendig, sowie der Blick in das Log-File, ob alles korrekt abläuft.

# systemctl restart bind9
# tail -f /var/log/bind.log

Automatische Aktualisierung des DNS-Server

Soweit ist der DNS-Server bereit, authentifizierte Veränderungen an der Zonendatei entgegen zu nehmen. Während der Laufzeit des Servers erfolgt das mit 'nsupdate' und dem zuvor erstellten Private-Key.

# nsupdate -k /etc/ssl/Kdyndns.example.org.+163+46242.private
> server ns.example.org
> zone example.org
> update delete dyndns.example.org
> update add dndns.example.org 18000 A 84.189.213.55
> send

 Übersetzt heißt das "Füge dem Nameserver 'ns.example.org' in der Zone 'example.org' einen neuen A-Record mit dem Namen 'dndns.example.org' hinzu, nachdem du den alten Eintrag 'dyndns.example.org' gelöscht hast. Die dazugehörige TTL beträgt 5 Stunden und die IP-Adresse 84.189.213.55".

Automatisierung des Updates

Mit Hilfe des folgenden Scriptes und einem Cronjob lässt sich der eben beschriebene Prozess automatisieren.

########################################################################
#
# ddns-update
# Updates dynamic DNS zone entries
#
########################################################################


KEYFILE="/etc/ssl/Kdyndns.example.org.+163+46242.private
NAMESERVER="ns.example.org"
ZONE="example.org"
HOSTNAME="dyndns.example.org"
TTL="300"

if [ -z "$1" ]
then
  IPADDR="`curl -s ifconfig.me`"
else
  IPADDR="$1"
fi

(
  echo "server $NAMESERVER"
  echo "zone $ZONE"
  echo "update delete $HOSTNAME"
  echo "update add $HOSTNAME $TTL A $IPADDR"
  echo "send"
) | nsupdate -k $KEYFILE

# EOF

Wenn dem Script eine IP-Adresse übergeben wird, verwendet es diese. Ansonsten wird die IP-Adresse genommen, die durch die Übermittlung der Webadresse "ifconfig.me" zur Verfügung gestellt wird.

Auf der Client-Seite

Das Script 'ddns-update' wird normalerweise unter '/usr/local/bin/' abgelegt und ausführbar gemacht. Mit Hilfe eines Cronjobs zum Beispiel mit stündlicher Aktualisierung

$ crontab -e
00 * * * * /usr/local/bin/ddns-update

wird dafür gesorgt, dass der DNS-Server immer über die aktuelle IP-Adresse Bescheid weiß.
Dieser erzeugt eine binäre Zonendatei mit der Endung ".jnl" und etwa 15 Minuten später wird auch die eigentliche Zonendatei neugeschrieben.