Eigener DynDNS Dienst (mit Fritzbox und Hetzner)

Eine eigene Toplevel Domain die direkt immer auf die IP des Internetanschlußes zuhause zeigt. Quasi der eigene DynDNS-Dienst – ohne die Hilfe von (kostenlosen oder kostenpflichtigen) DynDNS-Providern. Das wärs!

Für dieses Setup brauchen wir:
– Eine Domain (in diesem Fall bei Hetzner registriert)
– Einen Slave-DNS Eintrag bei den Hetzner Namervern
– Einen root-Server der alles managed (in diesem Fall Ubuntu 14.04)

Als allererstes kurz zur Erklärung:
Für jede .de-Domain (die bei der denic registriert wird) braucht man zwei Namensserver welche sagen können welche IP hinter der Domain steckt.
Dies sind die autoritiven Nameserver.
Die Vorgaben der Denic möchten hier auch dass die Nameserver nicht genau die gleiche IP-Adresse haben (klar, oder?) aber auch nicht ähnliche Adressen (gleicher Netzbereich)

Da wir bei unserem root-Server nicht extra zwei IPs einrichten wollen, nur damit die Denic zufrieden ist, und da dass auch aus Ausfallgründen eher unpraktisch ist brauchen wir also noch einen zweiten Nameserver der nichts anderes macht als die Daten unsere Nameservers zu übernehmen.
Dies ist der sogenannte Slave-Nameserver und man kann diesen bei Hetzner einfach per Klick bestellen (bzw. einen Eintrag auf dem Nameserver, einen ganzen Nameserver brauchen wir ja nicht!).

Für diese Anleitung gehen wir davon aus dass wir unseren root-Server meinroot.de haben und die Domain meinzuhause.de uns gehört.

Zuallererst installieren wir auf meinroot.de den DNS-Server bind:

apt-get install bind9

Bind bekommt eine Zonendatei für meinzuhause.de, diese liegt in ‚/etc/bind/db.meinzuhause.de‘ und sieht wie folgt aus:

$ORIGIN .
$TTL 60; 1 minute
meinzuhause.de          IN SOA  www.meinroot.de. dn.meinroot.de. (
                               2014090711; serial
                               7200; refresh (2 hours)
                               1800; retry (30 minutes)
                               604800; expire (1 week)
                               21600; minimum (6 hours)
                               )
                       NS      ns1.first-ns.de.
                       NS      www.meinroot.de.
                       NS      robotns2.second-ns.de.
                       A       89.14.9.131
                       MX      10 mail.meinzuhause.de.meinzuhause.de.
                       AAAA    2002:590e:2e2e:0:e1e3:60f5:97d:9429
$ORIGIN meinzuhause.de.
mail                    CNAME   meinzuhause.de.
www                     CNAME   meinzuhause.de.

Jetzt erzeugen wir einen Update-Key damit wir die Datei programmtechnisch updaten dürfen:

/usr/sbin/ddns-confgen -z meinzuhause.de

Diesen Key schreiben wir in die Keydatei ‚/etc/bind/ddns-key.meinzuhause.de.conf‘:

key "ddns-key.meinzuhause.de" {
       algorithm hmac-sha256;
       secret "CTQpYK6Dfdsf334fsd08LSY7ApziY3423fds8zw=";
};

Das Key-File müssen wir in der bind-Config ‚/etc/bind/named.conf‘ inkludieren:

// Update-Keyfile
include "/etc/bind/ddns-key.meinzuhause.de.conf";

Und den Key nochmal hinterlegen in ‚/etc/bind/named.conf.local‘:

zone "meinzuhause.de" {
      type master;
      file "/etc/bind/db.meinzuhause.de";
       update-policy { grant ddns-key.meinzuhause.de zonesub ANY; };
};

Nun müssen wir noch erlauben dass die Hetzner-Nameserver einen Zonentransfer machen dürfen, Datei ‚/etc/bind/named.conf.options‘ eintragen:

// Zonen-Transfer fuer Hetzner Nameserver
allow-transfer { 213.239.242.238;213.133.105.6;193.47.99.3; };

Jetzt brauchen wir noch ein Script welches von außen das Updaten des DynDNS-Eintrages vornimmt – und (als extrawurst) auch gleich noch einen Eintrag in eine Mysql-Tabelle durchführt:
Bühne frei für ‚/root/bin/dyndns.sh‘:

#!/bin/bash

NS="127.0.0.1"
NSKEY="/etc/bind/ddns-key.meinzuhause.de.conf"
TMPFILE="/var/www/html/dyndns.txt"
ZONE="meinzuhause.de"
TIMEOUT=60

OLDIP=$(dig @$NS $ZONE A | grep ^$ZONE.*A | awk '{ print $5 }')
NEWIP=$(cat $TMPFILE)

echo "old: $OLDIP"
echo "new: $NEWIP"

if [ "$OLDIP" != "$NEWIP" ]; then
       echo -e "
       update delete $ZONE. A
       update add $ZONE. $TIMEOUT A $NEWIP
       show
       send" | /usr/bin/nsupdate -k $NSKEY
       rndc freeze $ZONE
       rndc thaw $ZONE
else
       echo "no update required"
fi

Dieses Script holt die aktuelle IP aus der Datei ‚/var/www/html/dyndns.txt‘ und kümmert sich sowohl um das Update des Nameservers,
als auch ums weiterleiten der Zonendaten an die Hetzner-Slave Nameserver.
Dieser Cronjob (unter root) ruft das Script minütlich auf:

*       *       *       *       *       /root/bin/dyndns.sh > /dev/null 2>&1

Jetzt brauchen wir nur noch ein PHP-Script welches von außen per URL erreichbar ist und die Datei ‚/var/www/html/dyndns.txt‘ mit der übergebenen IP beschreibt, das packen wir unter ‚/var/www/html/dyndns.php‘:

<?php

$username = "meintollerdnydnsdienst";
$pass = "miteinemgeheimenpasswort";
$dyntxt = "/var/www/html/dyndns.txt";
$db = "dyndnsoettingen";

if($username == $_GET['username'] && $pass == $_GET['password'])
{
       $a = fopen("$dyntxt", "w");
       fwrite($a, $_GET['ipv4']);
       fclose($a);

       $mysqli = new mysqli("localhost", $username, $pass, $db);
       if ($mysqli->connect_errno)
       {
           echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
       }

       if (!$mysqli->query("INSERT INTO dyndns(domain, ipv4, ipv6) VALUES ('" . $_GET['domain'] . "', '" . $_GET['ipv4'] . "', '" . $_GET['ipv6'] . "')"))
       {
               echo "Insert-Error: (" . $mysqli->errno . ") " . $mysqli->error;
       }

       mysqli_close($mysqli);

       echo "success";
}

?>

Username und Passwort werden nicht nur im Script geprüft um zu checken ob derjenige den Update machen darf,
sie werden auch gleich zum anmelden an Mysql genutzt. Es muss also der entsprechende Mysql-Nutzer existieren.
Das Tabellenformat ist einfach:

CREATE TABLE `dyndns` (
  `updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `domain` varchar(256) CHARACTER SET utf8 NOT NULL,
  `ipv4` varchar(25) CHARACTER SET utf8 NOT NULL,
  `ipv6` varchar(100) CHARACTER SET utf8 NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

ACHTUNG: Nach einer Diskussion im Serversupportforum möchte ich noch auf folgende Sicherheitsvorgaben hinweisen:
Das Script hat ein großes Gefahrenpotential weil die weiterverarbeitung der Daten unter dem User ‚root‘ erfolgt. Sollte man diese Lösung also produktiv verwenden wollen sollte man ein paar Sicherheitsvorkehrungen treffen:
1. Der DB-User sollte so wenig Rechte wie möglich haben. Es reicht wenn er einen Insert in eine Tabelle machen kann.
2. Die Input-Parameter (ipv4, ipv6) sollten mit einem Regex überprüft werden ob sie wirklich IP-Adressen sind.
3. Der Vergleich auf Passwort und Usernamen sollte nicht mit ‚==‘ sondern mit ‚===‘ durchgeführt werden weil da auch sichergestellt wird dass die Variablen typgleich sind – also beide String.
4. Alle SQL Statements sollten nicht direkt ausgeführt werden, sondern als prepared Statements damit sie gegen SQL Injections abgesichert sind!

Nun müssen wir bei Hetzner einen Slave-DNS Eintrag bestellen, dort tragen wir die IP von meinroot.de ein.

Bei der Denic hinterlegen wir nun als Nameserver 1 unseren meinroot.de und als Nameserver 2 irgendeinen der Hetzner-Nameserver (ns1.first-ns.de, robotns2.second-ns.de, robotns3.second-ns.com)

Nun sollten wir alles schon gut mit dem Aufruf der URL testen und debuggen können. Zum prüfen was die Nameserver gerade als IP für meinzuhause.de rausgeben dienen folgende Befehle:

dig @127.0.0.1 meinzuhause.de
dig @www.meinroot.de meinzuhause.de
dig @ns1.first-ns.de meinzuhause.de
dig @robotns2.second-ns.de meinzuhause.de

Die Fritzbox bekommt nun folgende Konfiguration unter DynDNS:

Dynamic DNS-Anbieter: Benutzerdefiniert
Update-URL: https://www.meinroot.de/dyndns.php?username=<username>&password=<pass>&domain=<domain>&ipv4=<ipaddr>&ipv6=<ip6addr>
Domainname: meinzuhause.de
Benutzername: meintollerdnydnsdienst
Kennwort: miteinemgeheimenpasswort

Meine Fritzbox brachte hier noch im Systemlog alle paar Minuten folgenden (nicht tragischen) Fehler:

Dynamic DNS-Fehler: Die Dynamic DNS-Aktualisierung war erfolgreich, anschließend trat jedoch ein Fehler bei der DNS-Auflösung auf.

Wenns einen ströt wird man das los indem man sich mit Telnet auf die Fritzbox verbindet und die Datei ‚/var/flash/ar7.cfg‘ so verändert dass under ‚liveday‘ ‚1d‘ steht.
(UPDATE: Es muss ‚livedelay‘ – siehe hierzu der Kommentar von Andreas Richter!)

Und nun noch zum Disclaimer:
Ich hab die Anleitung anhand meiner Notizen zusammengesucht. Bei mir funktioniert das Setup. Wenn es bei euch nicht funktioniert,
bitte einen Kommentar absetzen dann kriegen wir das gemeinsam hin.
Sicherheitstechnisch ist es gut möglich dass das Setup nicht perfekt ist. Scripte die als root laufen und teilweise eingaben nicht absolut sauber validiert übernehmen sind natürlich bäh bäh!
Wer es also einsetzt sollte es bitte gut absichern.
Sollte irgendwas an der Anleitung falsch sein, oder jemand einen guten Tipp haben: Bitte einen Kommentar da lassen!

Teile der Anleitung habe ich von hier: MyNakedGirlfriend.de
(keine Angst, trotz des Namens kein xxx-content – dafür aber in den Kommentaren eine Interessante Diskussion. Sollte man vielleicht mal lesen!)

Hier gibt es noch eine weiter Anleitung dazu: nicht-traeumen-sondern-machen.de

Zur Konfiguration von Bind hilft Ubuntuusers.de weiter.


Beitrag veröffentlicht

in

, , ,

von

Schlagwörter:

Kommentare

24 Antworten zu „Eigener DynDNS Dienst (mit Fritzbox und Hetzner)“

  1. maikel

    Ich habe einen Rootserver bei Hetzner und auch eine Domain von dort (meinrootserver.de). Jetzt würde ich aber gerne statt einer weiteren Domain (meinzuhause.de) eine Subdomain (h.meinrootserver.de) über DynDNS auf meine Heim-IP zeigen lassen. Hierbei habe ich aber Probleme mit der Angabe der Nameserver bei Hetzner, da das afaik nur für Domains, nicht aber für Subdomains geht.

    Kann man dein Setup für diese Umständen anpassen?

    1. Thomas

      Hallo maikel,

      denke das geht. Gib mir mal ein bissl Zeit um ne Musterlösung zu basteln…

      Thomas

    2. Thomas

      Hallo maikel,

      ich denke das einfachste wäre wirklich wenn dein BIND Server die komplette Domain verwaltet und die Hetzner Nameserver diese nur transferieren. Du kannst ja deine IP Daten für die Domain fest im Updatescript eintragen und dann nur eine Subdomain aktualisieren lassen.

      Spricht da was dagegen, oder geht das?

      Am einfachsten wird es wohl sein wenn du im Script für BIND statt $newip einfach deine richtige IP einträgst.

      Dann musst du nur noch mit:
      >>>
      update add zuhause.$ZONE. $TIMEOUT A $NEWIP
      <<< die Subdomain eintragen. Den Rest kannst du fest eintragen: >>>
      update add $ZONE. $TIMEOUT A 123.123.123.123
      <<< Natürlich muss hier noch das weitere mitrein. MX Eintrag und sowas. Aber das ist ja nicht mehr schwie5rig. Kannst du das mal versuchen? Thomas

  2. maikel

    Hallo Thomas,

    danke für deine Antwort.

    Ich versteh das jetzt so, dass ich auf meinem Rootserver einen Master Nameserver laufen lassen soll und be Hetzner dann den Slave. Oder was meinst du mit komplette Domain verwalten und die Hetzner Nameserver nur transferieren? Maikel

    1. Thomas

      Hallo maikel,

      genau so. Dein Nameserver wird (zusammen mit einem Hetzner NS) bei der Denic als autoritiver Nameserver eingetragen. Der Hetzner Nameserver kopiert nur die Daten von dir (als Slave, ihm wird der Zonentransfer erlaubt).

      Es ist also alles exakt genauso wie in meiner Anleitung – nur dass du eben bei jedem Update verschiedene Einträge (A, MX, …) fest setzt und nicht den A Eintrag der Domain, sondern der Subdomain updatest.

      Thomas

      1. maikel

        Hallo Thomas,

        danke nochmal für deine Antwort.

        Ich werde das am Wochenende mal ausprobieren und hier Berichten.

        maikel

        1. maikel

          Hallo Thomas,

          hat jetzt alles etwas länger gedauert, hab’s aber nun hinbekommen.

          Mein Rootserver ist nun der Master-Namerserver zu meiner Domain, Hetzner hat den dazugehörigen Slave.
          Ich update bei jedem IP-Wechsel ausschließlich den Eintrag für die Subdomain, die auf die dynamische IP zeigt. Das heißt die einzige Änderung in „dyndns.sh“, ist:

          update delete $ZONE. A
          update add $ZONE. $TIMEOUT A $NEWIP
          wird zu
          server localhost
          zone meinrootserver.de
          update delete h.$ZONE. A
          update add h.$ZONE. $TIMEOUT A $NEWIP

          Die ersten beiden Einträge musste ich hinzufügen, da ich sonst einen NOTIMP-Error von nsupdate erhalte.

          Ansonsten musste ich die Zonendatei natürlich anpassen, da ja der Master-Nameserver unter der zu verwaltenden Domain liegt.

          Vielen Dank für deine Hilfe!
          maikel

          1. Thomas

            Hallo maikel,

            super das es geht!

            Thomas

          2. Alex

            Hallo Maikel,
            kannst du mir mal sagen, wie dein zonefile aussieht?

  3. Daniel

    Hallo zusammen,
    kleiner Tip noch am Rande wenn man das dyndns-Text file im tmp nicht von aussen schrieben möchte wie oben beschrieben, sondern wie ich die aktuelle IP aus dem Router haben möchte. Sprich die, die auf die Fritzbox ist ohne dass man die Fritzbox dazu nötigt ein Befehl abzusetzen (bei mir läuft keine Fritzbox sondern ein anderes Modem was dyndns nicht unterstützt). Dann kann folgendes Kommando verwendet werden:

    dig +short myip.opendns.com @resolver1.opendns.com

    Sauschnell und bringt die aktuelle IP zurück.

    Gruss,
    Daniel

  4. bei mir geht das irgend wie nicht anmelden kein problem aber in der dyndns.txt kommen nicht die ip rein die fritzbox hat.

    1. Thomas

      Hallo Reddin,

      ich würd dir gerne helfen.

      Wenn du magst kannst du mir eine Mail schreiben und wir sehen uns das gemeinsam (z.B. über Teamviewer) mal an.

      Ich bin zwar jetzt erstmal im Urlaub, aber ab nächste Woche Donnerstag wieder da!

      Thomas

  5. Michael

    Hallo Thomas,
    zunächst mal danke für die tolle Anleitung. Mit dieser konnte ich einen eigenen DydDNS – Dienst weitestgehend problemlos einrichten.

    Eine Anmerkung jedoch:
    ich würde die Zonendatei(en) ins /var/lib/bind – Verzeichnis packen und den bind – User die Ownership geben.

    Zumindest bei mir (Ubuntu 16.04.2) hat nsupdate immer gemeckert, dass er kein Journal schreiben kann (/etc/bind gehört nicht bind). nsupdate versucht wohl immer ein Journal im gleichen Verzeichnis anzulegen, wo die Zonendatei liegt.

    Gruß
    Michael

    1. Patrick

      Hallo Thomas, hallo Michael,

      Thomas, herzlichen Dank für die gute Anleitung, ich habe sie zu über 99% für meinen Usecase übernommen.

      Was habe ich noch angepaßt:
      1.) Die Zonen-Datei, die aktualisiert werden soll, habe ich nicht nach /var/lib/bind geschoben, sondern nach /etc/bind/dynamic-zones/.
      Auf dieses Verzeichnis habe ich ein chmod g+w gesetzt.

      2.) Da ich nur einen Eintrag in der Zone aktualisieren möchte, habe ich die Permissions vom Key eingeschränkt auf „grant $key name $record $type“, wobei $record bei mir ein A-Record ist und somit $type „A“.

      3.) Ich habe von Daniel den Tip mit opendns übernommen, so daß ich meine aktuelle IP über „dig +short myip.opendns.com @resolver1.opendns.com“ ermittle. Die Zeile im Skript sieht so aus:
      NEWIP=$(dig +short myip.opendns.com @resolver1.opendns.com)

      4.) Wegen 3. setze ich im Skript noch
      „server $NS“ und „zone $ZONE“

      5.) Die TTL habe ich auf 3600 gesetzt (Geschmackssache)

      Nochmals vielen Dank und viele Grüße

      Patrick

  6. Hier hat sich ein Tippfehler eingeschlichen:

    Datei ‚/var/flash/ar7.cfg‘ so verändert dass under ‚liveday‘ ‚1d‘ steht.

    Es muss nicht ‚liveday‘, sondern ‚livedelay‘ heissen. Der betreffende Sektor ist der unter ddns. Und Telnet geht auch nicht mehr bei neueren Firmwareversionen der Fritzbox. Aber man kann die Konfigdatei sichern, mit einem Editor bearbeiten und dann die Prüfsumme (letzte zeile der Datei) mit einem entsprechenden Tool neu kalkulieren und eintragen. Diese Datei neu in die FB einspielen – und die Fehlermeldung ist weg.

    1. Thomas

      Hallo Andreas,

      vielen Dank für den Hinweis!

      Thomas

  7. Hallo Thomas,

    tolle Anleitung – ich bin kurz davor, dass es klappt 🙂

    Dummerweise meckert mir Ubuntu das dyndns-script an und gibt folgendes aus:

    incorrect section name: -e
    syntax error
    The zone reload and thaw was successful.

    Doe Zone wird nie geupdated.
    Was mache ich falsch?

    1. Thomas

      Du musst irgendwo einen vertippser drin haben. Kannst mir mal das Script schicken?

  8. David

    Wie habt ihr das Problem mit der Serial gelöst?
    Nach jedem Update „meckert“ mein Bind logischerweise, weil sich zwar Daten geändert haben, die Serial aber nicht?

    1. Thomas

      Bei mir gabs da nichts zu lösen, der BIND liefert trotzdem die aktuellen Daten aus…

  9. Noah

    Guten Tag, ich habe mal ne kurze frage und hoffe das sie gelesen wird. Mein DNS Server funktioniert super und der PHP Script auch. Nur bei dem shell Script bekomme ich einen Fehler.
    Shell Ausgabe: https://imgur.com/DN9h8XN

    1. Thomas

      Sieht für mich so aus als sei entweder der Update Key nicht erzeugt, nicht eingetragen oder aber nicht zugreifbar für den jeweiligen Nutzer (also der Nutzer der das PHP-Script startet, wahrscheinlich www-data). Prüfe diese Punkte mal!

      1. Noah

        Habe alles überprüft, Key nochmal erstellt Pfade überprüft und Rechte gecheckt. Gibt es noch eine andere Möglichkeit den TSIG Key zu erstellen weil alles deutet darauf das er ungültig bzw. von bind nicht erkannt wird. Ich bedanke mich für ihre Bemühungen im Voraus.

  10. Sascha

    Hallo Thomas,
    ich nutze ein LEMP-Stack mit einem reverse-Proxy nginx Server. Zerschieße ich mir da meine Version mit bind9? Oder sind das voneinander unabhängige Systeme?
    Mein Ziel: Mein Raspbery zuhause (Hausautomation) über meinen öffentlichen Server in Nürnberg laufen lassen.
    Quasi:
    Hausautomation.meinServerInNürnberg.de

    Reicht da nicht eig ein Eintrag in der DNS-Zonenverwaltung des Anbieters?

    Dabei will ich meine funktionierenden Systeme nicht schrotten:
    jitsimeet.meinServerInNürnberg.de
    meinServerInNürnberg.de/nextcloud

Schreibe einen Kommentar zu maikel Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert