Dynamische DNS-Updates mit Bind
Manchmal habe ich ja komische Ideen von Dingen, die ich unbedingt brauche. Vor einiger Zeit schon hatte ich mir in den Kopf gesetzt mal unbedingt Dienste wie DynDNS abzulösen und das ganze selbst in die Hand zu nehmen.
Nun bin ich in der sehr komfortablen Situation, dass mein Hoster es mir ermöglicht fast alle Details des DNS zu ändern, so dass ich auch meine eigenen Nameserver eintragen kann. Nun bin ich kein Experte auf dem Gebiet der .eu-Regularien, weiß aber, dass für .de-Domains zwei Nameserver aus unterschiedlichen Class-C-Netzen notwendig sind. Das erhört die Hürde also noch ein wenig…
Aber wozu hat man Freunde, die genauso bekloppt sind und auch einen eigenen Server haben. So kann man das Problem dann sehr elegant mit der Master-Slave-Replikation von Bind lösen, aber dazu später mehr.
Zunächst einmal gilt es Bind zu installieren und die grundlegende Configuration vorzunehmen. Ich arbeite mit der Version 9.3.4, die zwar nicht brandaktuell ist, aber bei meiner Lieblingsdistribution zum Lieferumfang gehört.
apt-get install bind9 dnsutils
Nun wechseln wir in das Verzeichnis /etc/bind
, um dort die entsprechenden Dateien anzulegen bzw. zu bearbeiten. Zunächst bearbeiten wir die named.conf.local
. Eine Beispielconfiguration könnte wie folgt aussehen:
Zeile 13 gibt an, dass wir für die Zone/Domain der
Masterserver sind und sich die Details in der Datei
/etc/bind/db.schnuckelig.eu
befinden. Des weiteren
verschicken wir keine Benachrichtigunten an sekundäre Nameserver (Zeile
12).
Da wir uneren Server automatsich aktualisieren wollen ist es sicher ratsam über Sicherheit ein wenig nachzudenken. Wir müssen, naja, wollen, ja den Zugriff beschränken. Das können wir über eine IP (blöd) oder anderweitige Authentifizierung machen.
Wir müssen uns nun für eines der Verschlüsselungsverfahren entscheiden, symmetrisch (TSIG) oder asymetrisch (SIG(0)). Beides hat vor und Nachteile, ich habe mich aber für die etwas aufwändigere, aber schnuckeligere Variante entschieden, also asymetrisch. Im LAN würde ich wegen der einfacheren Configuration wohl eher TSIG nehmen.
Den Schlüssel erstellen wir am einfachsten mit ```dnssec-keygen -a
K++.key</code> erzeugt.
Jetzt müssen wir die Zonendatei erstellen und den öffentlichen Schlüssel dort
eintragen.
$ORIGIN .
$TTL 600
schnuckelig.eu IN SOA ns.schnuckelig.eu. hostmaster.schnuckelig.eu. (
200804111 ; serial
28800 ; refresh (8 hours)
7200 ; retry (2 hours)
2419200 ; expire (4 weeks)
86400 ; minimum (1 day)
)
NS ns.schnuckelig.eu.
NS ns.andere-domain.de.
MX 10 mail1.schnuckelig.eu.
MX 20 mail2.schnuckelig.eu.
$ORIGIN schnuckelig.eu.
$INCLUDE /etc/bind/Kzuhause.schnuckelig.eu+005+12345.key
www A 123.456.789.1
Super, alles toll soweit, jetzt kann es ja losgehen. Noch nicht ganz. Wir
müssen jetzt noch in der Zone eintragen wer hier überhaupt etwas
aktualisieren darf und was. Es gibt dazu zum einen
```allow-update```, welches aber nur generellen Zugriff gewährt.
Ich habe also keine weiteren Möglichkeiten der Rechtevergabe. Besser ist
da schon ```update-policy```. Damit kann ich einzelnen Hosts die
Rechte genau zuweisen, also nicht nur wer, sondern auch
was.
Unsere Zone sieht nun also wie folgt aus:
//
// Do any local configuration here
//
// vi: ts=4 sw=4
// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";
zone "schnuckelig.eu" {
type master;
notify no;
file "/etc/bind/db.schnuckelig.eu";
update-policy {
grant zuhause.schnuckelig.eu. name zuhause.schnuckelig.eu. A TXT;
}
};
Somit kann nur der Rechner zu Hause den A- und TXT-Record aktualisieren.
Was uns jetzt noch fehlt ist ein kleines Skript, welches das Update
selbstständig durchführt. Kein Problem, das ganze sieht wie folgt aus:
```bash
#!/bin/sh
# ddns.sh
# Update des DNS via nsupdate
# Usage: ddns.sh
TTL=3600
SERVER=
HOSTNAME=zuhause.schnuckelig.eu
KEYFILE=Kzuhause.schnuckelig.eu.+005+12345.key
IP=$1
nsupdate -v -k $KEYFILE > /dev/null << EOF
server $SERVER
update delete $HOSTNAME A
update add $HOSTNAME $TTL A $IP
send
EOF
```
Wobei der öffentliche und auch der private Schlüssel in demselben
Verzeichnis liegen müssen. Aber wer möchte das schon immer manuell machen
müssen. Eleganter wäre es ja dies direkt bei der Einwahl zu erledigen.
Nichts leichter als das, mit dem richtigen Betriebssystem
zumindest.
Alle ausführbaren Dateien in ```/etc/ppp/ip-up.d/``` werden bei der
Einwahl ausgeführt und erhalten eine Reihe von interessante Parametern.
```bash
#!/bin/sh
# # These variables are for the use of the scripts run by run-parts
# PPP_IFACE="$1"
# PPP_TTY="$2"
# PPP_SPEED="$3"
# PPP_LOCAL="$4"
# PPP_REMOTE="$5"
# PPP_IPPARAM="$6"
TTL=3600
SERVER=
HOSTNAME=zuhause.schnuckelig.eu
KEYFILE=Kzuhause.schnuckelig.eu.+005+12345.key
/usr/bin/logger -p info "Dynamic DNS update: $PPP_IFACE $PPP_TTY $PPP_LOCAL"
nsupdate -d -k $KEYFILE <<-EOF
server $SERVER
update delete $HOSTNAME A
update add $HOSTNAMNE $TTL A $PPP_LOCAL
send
EOF
```
So, damit wäre auch schon alles erledigt. Zumindest für unseren Teil, aber
es fehlt ja noch der Abgleich mit dem secondary name server. Dazu
bietet sich eine Master-Slave-Replikation an. Bei Bind muss man dazu den
Incremental
Zone Transfer (IXFR) einrichten.
Das ist relativ einfach für den Master. Dort brauchen wir für die Zone
schnuckelig.eu einfach nur
notify explicit;
also-notify { ; };
</blockcode>
anzugeben und schon sind wir fertig. Es können natürlich auch mehrere
Adressen angegeben werden.
Auf der Slave-Seite ist die Configuration auch nicht weiter schwierig. Wir
erstellen dazu auch eine analogue Zone mit den notwendigen Slave-Angaben.
zone "schnuckelig.eu" {
type slave;
masters { ; };
allow-notify { ; };
allow-transfer { ; };
file "/etc/bind/db.schnuckelig.eu";
};
</blockcode>
Noch mal eben beide Server durchstarten, glücklich sein und genießen :).
Einige Punkte sind noch offen. Man könnte sich z. B. überlegen die
dynamischen Einträge alle in eine eigene Subdomain zu verlegen und in der
Hauptdomain nur per CNAME darauf zu verweisen. Des weiteren ist die
Configuration sicher nicht die sicherste. Statt die IP-Adresse des
Masters einzutragen könnte man TSIG, also dem
symmetrischen Verfahren, benutzen. Auch sollte man sicher Optionen wie
allow-recursion noch anpassen.
Aber das beschreibe ich dann (vielleicht) mal in einem weiteren Beitrag...