Eigener DynDNS-Dienst

Wenn man Nameserver von InternetX verwalten lässt kann man sich leicht einen eigenen DynDNS-Dienst aufsetzen in dem man die XMP-RPC-Schnitstelle des AutoDNS nutzt, da die InternetX-Nameserver Änderungen in Echtzeit aktivieren. Meine Version basiert hierauf: http://ph-blog.de/dyndns-via-php-script-auf-internetx-dns/

Um das Ganze von allen anderen Domains abzugrenzen empfehle ich einen eigenen Benutzer und eine eigene Domain dafür im AuotDNS anzulegen. In der Zone habe ich die default TTL auf 180 gesetzt. Für jeden Host mit dynamischer IP muss ein A-Record, idealer Weise auch mit der kurzen TTL, angelegt werden. Das Script liesst dann die Zone, passt die IP an und schreibt die Zone zurück.

Update: Context verallgemeinert um „Personal AutoDNS“ zu unterstürzen.

$ip      = $_SERVER["REMOTE_ADDR"];
$user    = "autodnsuser";      // AutoDNS-User
$pass    = "autodnspasswort";  // Passwort des AutoDNS-Users
$context = "4";                // Default Contxt: 4
$domain  = "dyndomain.de";     // Domain die verwendet werden soll
$ns      = "a.ns14.net";       // InternetX-Nameserver der bei der Domain verwendet wird

$u = $_GET["hostname"];

define( 'HOST', 'https://gateway.autodns.com' );

$authXML = "<auth> <user>". $user .
"</user> <password>" . $pass .
"</password> <context>" . $context .
"</context> </auth> ";

$requestXML = "<request>" . $authXML .
"<task> <code>0205</code> <zone> <name>" . $domain .
"</name> <system_ns>" . $ns .
"</system_ns> </zone> <key></key> </task> </request> ";

$updateXML = "<request>" . $authXML .
"<task> <code>0202</code> </task> </request> ";

function requestCurl( $data ) {
        $ch = curl_init( HOST );
        curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
        if( !$data = curl_exec( $ch )) {
                echo 'Curl execution error.', curl_error( $ch ) ."\n";
                return FALSE;
        }
        curl_close( $ch );
        return $data;
}


$xmlInput = requestCurl( $requestXML );

// Zone laden
$dom=new DOMDocument();
$dom->preserveWhiteSpace = false;
$dom->loadXML($xmlInput);
$zone=$dom->getElementsByTagName('zone');

// changed und created tags entfernen
$node=$dom->getElementsByTagName('changed')->item(0);
$node->parentNode->removeChild($node);
$node=$dom->getElementsByTagName('created')->item(0);
$node->parentNode->removeChild($node);

// update template laden
$dom2=new DOMDocument();
$dom2->preserveWhiteSpace = false;
$dom2->loadXML($updateXML);
$zone2=$dom2->getElementsByTagName('zone');

// zone hinzfuegen
$new=$dom->getElementsByTagName("zone")->item(0);
$new=$dom2->importNode($new,TRUE);
$node=$dom2->getElementsByTagName("task")->item(0)->appendChild($new);

// IP anpassen
foreach( $dom2->getElementsByTagName("rr") as $node) {
	if ( $node->getElementsByTagName("name")->item(0)->nodeValue == $u &&
	     $node->getElementsByTagName("type")->item(0)->nodeValue == "A"   ) {
		if ($node->getElementsByTagName("value")->item(0)->nodeValue != $ip) {
			$node->getElementsByTagName("value")->item(0)->nodeValue = $ip;
			requestCurl( $dom2->saveXML() );
			error_log("Neue IP fuer " . $u . ": " .$ip);
		}
		else {
			error_log("IP unveraendert " . $u . ": " .$ip);
		}
		die("OK " .$u . " " . $ip);
	}
}
?>

Aufgerufen wird dass dann so:

http://webserver.de/?hostname=dynhostname

FIXME Passwort mit einbauen damit nicht einfach irgend wer Updates machen kann

Microtik Update-Scrtipt

:local DYNDNSHOSTNAME "name.dyndomain.de";
:local HOSTNAME "name";
:local EXTERNALINTERFACE "ether1-gateway";

:local currentIp [/ip address get [/ip address find interface=$EXTERNALINTERFACE] address];
:set currentIp [:pick $currentIp 0 [: find $currentIp "/"]];
:local oldIp [:resolve $DYNDNSHOSTNAME];

:if ($currentIp != $oldIp) do={
  :local addr "webserver.de";
  :local srcPath "/?hostname=$HOSTNAME";
  :local dstPath "dyndns.txt";

  /tool fetch address=$addr host=$addr src-path=$srcPath dst-path=$dstPath keep-result=no mode=http

  :log info "DynDNS updated: $DYNDNSHOSTNAME $oldIp -> $currentIp";
}

Leider bieten Mikrotik-Router keinen Trigger der ein Script ausführene würde wenn sich an einem Interface etwas ändert. Deshalb braucht man einen Scheduler-Eintrag, der dieses Script z.B. jede Minute laufen lässt. Das Script setzt die IP nur neu, wenn sie sich auch geändert hat.