Was lange währt wird endlich gut. Kommen wir zum Auslöser der gesamten
Geschichte.
Als Basis habe ich die Anleitung auf AWL-Home verwendet.
Da mit der Spaghetticode des PHP-Skripts nicht gefiel, habe ich es jedoch umgebaut (mehr dazu unten).
Mein Server hat zwar eine feste IP Adresse, Ihr Internetzugang in der Regel
jedoch nicht (im Moment haben Sie die IP 3.80.131.164, morgen vielleicht schon eine andere).
Dieses ständige "umgeziehe" macht es unmöglich, auf eigenen Rechnern Dienste im Netz anzubieten (z.B. den Zugang zur eigenen Cloud oder einen VPN-Tunnel).
Die Lösung dafür ist DynDNS. Wir können dem Rechner zwar keine eigene, öffentliche IP Adresse geben, einen eigenen Domainnamen schon.
Frage: Wenn der Rechner seine IP Adresse schnell mal ändern kann, woher weiß dann eigentlich der DNS Server, welche IP Adresse er zurückmelden muss?
Antwort: Der Rechner sagt einfach beim DNS-Server bescheid, dass sich seine IP Adresse geändert hat, indem er eine bestimmte Website aufruft. Über diese wird dann der DNS Eintrag geändert.
Die Idee des DynDNS Protokolls ist Flexibilität. Man kann u.A. mehrere Einträge gleichzeitig ändern, MX records setzen und vieles mehr.
Für meine Anforderungen genügt eine einfachere Fassung, bei der je Aufruf genau ein A-Record gesetzt wird.
Dazu verwende ich einfach den Namen der Subdomain als Benutzernamen, als IP wird immer die des Aufrufers verwendet, Mehrfach-Updates oder andere Recordtypen schließe ich aus.
Damit reichen für die Aktualisierung Benutzername und Passwort aus. Die Authentifizierung erledigt Apache, d.h. das Update-Skript wird nur dann aufgerufen, wenn Benutzername und Passwort korrekt sind.
Hier sind alle Einstellung bereits in Teil 1: Nameserver gemacht.
Zuerst legen wir unter htdocs auf dem Webserver einen Ordner (z.B. ddnsupdate) an, der uns später als Update-URL dient.
Ein zweiter Ordner auf der selben Ebene wie htdocs (z.B. passwd) nimmt die Passwortdatei auf.
Danach tragen wir im <VirtualHost> folgendes ein:
<Directory "/srv/www/www.beispiel.de/htdocs/ddnsupdate"> DirectoryIndex index.php AuthType Basic AuthName "DynDNS Update" AuthBasicProvider file AuthUserFile /srv/www/www.beispiel.de/passwd/dnsupdate.passwd Require valid-user </Directory>Als nächstes legen wir mittels htpasswd2 die Passwörter an (Hinweis: der Benutzername wird später auch der Name der Subdomain):
beispiel.de:/srv/www/www.beispiel.de/passwd # htpasswd2 -bc dnsupdate.passwd user1 <langes Passwort> beispiel.de:/srv/www/www.beispiel.de/passwd # htpasswd2 -b dnsupdate.passwd user2 <anderes langes Passwort> beispiel.de:/srv/www/www.beispiel.de/passwd # htpasswd2 -b dnsupdate.passwd user3 <noch ein anderes langes Passwort>Hinweis: Die Option -c im ersten Kommando legt die Datei dnsupdate.passwd neu an. Diese Option später nochmals zu versenden würde alle bisherigen Nutzer löschen.
Nachdem wir unseren passwortgeschützen Berecih auf dem Webserver haben, erstellen wir im entsprechenden Ordner eine "index.php" mit dem Update-Skript. Zum Beispiel dieses (das auch gern kopiert werden darf):
<?php $zone="ddns.beispiel.de"; function checkIP($ip) { $iptupel = explode(".", $ip); foreach ($iptupel as $value) { if ($value < 0 || $value > 255) return false; } return true; } function getDomain() { if (isset($_SERVER['REMOTE_USER'])) return $_SERVER['REMOTE_USER']; if (isset($_SERVER['PHP_AUTH_USER'])) return $_SERVER['PHP_AUTH_USER']; return ""; } function runUpdate($domain, $ip) { exec("/usr/bin/dynupdate $domain $ip", $cmdout, $ret); return $ret; } function logError($errtype, $msg) { syslog(LOG_INFO, $msg); echo $errtype." ".$msg; } header("Content-type: text/plain"); $error=0; openlog("DDNS Update", LOG_PID | LOG_PERROR, LOG_LOCAL0); $domain=getDomain(); if ($domain=="") { $error=1; logError("notfqdn", "Update failed. Could not get Domain"); } if ($error==0) { $ip=$_SERVER['REMOTE_ADDR']; if (!checkIP($ip)) { $error=1; logError("nohost", "Update failed. Could not get IP for Domain ".$domain."."); } } if ($error==0) { $ret=runUpdate($domain, $ip); if ($ret !=0) { $error=1; logError("dnserr", "Update command failed"); } } if ($error==0) { echo "good ".$ip." ".$domain.".".$zone; } echo "\n"; ?>Zusätzlich benötigen wir noch ein Shell-Skript (damit nsupdate nicht suid root laufen muss). Dieses legen wir unter /usr/bin/dynupdate an und setzen es mit chmod 4755 /usr/bin/dynupdate suid root.
#!/bin/bash zone="ddns.beispiel.de" zonekey="/etc/ddns/ddns.key" domain=$1 ip=$2 /usr/bin/nsupdate -k $zonekey <<EOF zone $zone update delete $domain.$zone A update add $domain.$zone 30 A $ip send EOF exitDie Skripte sind zwar noch nicht perfekt, funktionieren aber im Moment.
Das war es eigentlich schon. Einfach mal ausprobieren (die Update URL lautet im Beispiel "https://www.beispiel.de/ddnsupdate/"). Nach der Eingabe von Benutzernamen und Passwort sollte eine Erfolgsmeldung erscheinen und spätestens 60 Sekunden danach der Rechner über <username>.ddns.beispiel.de zu erreichen sein.
In der Konfigurationsoberfläche des Routers DynDNS auswählen, Anbieter auf benutzerdefinert stellen, Update-URL, Benutzernamen und Passwort eintragen, fertig.
Hinweis: Mindestens auf der Fritz!Box funktioniert das nur, wenn die Subdomain bereits existiert. Dazu vor dem Eintragen der Daten in die Fritzbox auf dem Server folgendes ausführen:
/usr/bin/dynupdate <subdomain> 127.0.0.1