DynDNS für PowerDNS
Durch meinen Umzug habe ich wieder das gute alte Problem: einen Telekom Anschluss mit einer dynamischen IP. Auf die Hosts dahinter würde gerne von überall unterwegs mittels VPN/IPSec zugreifen. Problem ist natürlich die eventuell wechselnde IP des Anschlusses selbst.
Stichwort DDNS. Lange Zeit hatte ich das mit no-ip.com realisiert. Da ich für linux-dev.de mittlerweile aber sowieso eigene DNS-Server betreibe, kann ich nun mit „hauseigenen“ Mitteln lösen.
Anbei ein kleines PHP-Script mit dem ich mir meinen eigenen kleinen DynDNS-Service auf PowerDNS-Basis hoste. Ratsam ist natürlich TTL für den betreffenden Record extrem niedrig zu setzen.
<?php /** * DynDNS-Service für PowerDNS */ $dsn = 'mysql:dbname=pdns;host=127.0.0.1'; // Datenbank DSN $user = 'pdns'; // Name der Datenbank $pass = 'password'; // Datenbank Passwort // Auth-String der als GET-Parameter übermittelt werden muss $auth = 'hiddenstring'; // Für alle im Array enthaltenen Records dürfen Updates gefahren werden $allowed = array('somehost.linux-dev.de'); $domain = (isset($_GET['domain'])) ? $_GET['domain'] : null; $ip = (isset($_GET['ipaddr'])) ? $_GET['ipaddr'] : null; if ((empty($domain) || is_null($domain)) || (empty($ip) || is_null($ip))) { die('missing parameter'); exit; } if (!in_array($domain, $allowed)) { die('forbidden domain name'); exit; } if (!isset($_GET['passwd']) || $_GET['passwd'] != $auth) { die('authentification failed'); exit; } try { $dbh = new PDO($dsn, $user, $pass); } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); } $check = $dbh->prepare('SELECT id FROM records WHERE name = :name AND type = :type'); $check->bindParam(':name', $domain); $check->bindValue(':type', 'A'); $check->execute(); $result = $check->fetch(PDO::FETCH_ASSOC); if (empty($result)) { die('record not found'); exit; } else { $update = $dbh->prepare('UPDATE records SET content = :content WHERE id = :id LIMIT 1'); $update->bindParam(':content', $ip); $update->bindParam(':id', $result['id']); if ($update->execute()) { die('update successful (' . htmlentities($ip, ENT_QUOTES) . ')'); exit; } die('update returned false'); exit; } ?>
Bleibt noch die Konfiguration des DynDNS-Clients in der Fritzbox (in meinem Fall eine 7390). Diese sieht in meinem Fall so aus:
- Dynamic-DNS-Anbieter: Benutzerdefiniert
- Update-URL: http://foo.linux-dev.de/update.php?domain=<domain>&ipaddr=<ipaddr>&passwd=<pass>
- Domainname: somehost.linux-dev.de
- Benutzername: beliebig (in diesem Script nicht benutzt)
- Kennwort: hiddenstring
Und schon funktioniert das ganze – vollkommen unabhängig von Diensten wie DynDNS.com oder No-IP.com.
Dein Skript an sich funzt. Nur leider hat es ein kleines Problem… es zählt die Seriennummer im SOA Eintrag nicht hoch.
Wenn ich jetzt einen Slave Server habe der über axfr seine Daten aktuell halten soll, klappt das nicht. Da dieser die Seriennummer kontrolliert und feststellt das es keine Veränderung gibt.
Hi Denis,
da hast du vollkommen Recht. Bei mir lief der PowerDNS auch als Hidden Master mit Zone Transfer zu mehreren BINDs. Ich kann mich zumindest nicht erinnern in diese Probleme gelaufen bin, an sich stimme ich dir aber voll zu. Normalerweise sollte ein Slave ohne Anpassung des Serials nichts von der Aktualisierung mitbekommen.
Ich würde dich hier zwar gerne unterstützen, ich habe jedoch mittlerweile keinen PowerDNS Server mehr in Betrieb um das ganze nachzuvollziehen. Ich setze mittlerweile auf Cloudflare und AWS Route 53.
Ein zusätzlicher Query mit UPDATE auf die Serial wäre denke ich ein guter Anfang um das Problem zu lösen. Falls du das Problem gelöst hast kannst du es gerne hier teilen damit der Artikel aktualisiert werden kann.
Als Alternative unterstützt PowerDNS mittlerweile auch RFC2136 (https://doc.powerdns.com/md/authoritative/dnsupdate/). Hierzu gibt es sicherlich auch einen REST Wrapper bei GitHub und Co.
[…] Script, welches ich genutzt habe, stammt von Simon Lauger. Auf seiner Website hat er dieses veröffentlicht. Für meine Zwecke habe ich das Script minimal […]