Wie bastle ich mein eigenes dynDNS

$Revision: 1.6 $, $Date: 2005-04-21 21:33:36 +0200 (Thu, 21 Apr 2005) $, $Author: root $

Als erstes generiert man sich einen Schlüssel:

dnssec-keygen -a HMAC-MD5 -b 512 -n HOST <keyname>
512 ist für die Leute mit Paranoia, ich selbst habe nur einen 128er Schlüssel.

Heraus kommen Zwei Dateien:

Der Schlüssel steckt in beiden drin.

Dann macht man auf dem DNS-Server im named.conf einen solchen Eintrag:

key "foo_key" {
        algorithm hmac-md5;
        secret "das was dnssec-keygen ausgespuckt hat";
};
Der eigentliche Zone Eintrag der Domain foo wird dann noch um folgende Zeile ergänzt:
allow-update { key foo_key; };
Das wars zur Serverseite!

Die clientseite sieht so aus:

Mit dem Befehl nsupdate kann man alle Einträge im Zonefile löschen, und neu anlegen, wenn man den Key kennt. In userem Beispiel sähe das dann so aus (Achtung, die Leerzeile ist relevat!):
$ nsupdate -v -y 'foo_key:+das was dnssec-keygen ausgespuckt hat'
> server gnuher.de
> update delete dynip.foobar.de. in a
> update add dynip.foobar.de. 300 in a "neue dynamische ip"
>
> quit
300 ist die TTL von 300 Sekunden, da kann man auch nen andren Wert verwendden. Da das ein wenig umständlich ist hab ich ein script gebaut, das ich aus ip-up aufrufe (Achtung in tcl geschrieben ;).
--schnipp--
#!/usr/bin/tclsh
#
# Update a given hostname with a given IP Number

### These are configurable options

# The update Key, as specified in "named.conf" of the Server
set update_key {foo_key:+das was dnssec-keygen ausgespuckt hat}

# TTL for the Dynamic A Record
set TTL 300

# the name of the dynamic A Record (inclues an additional DOT!!)
set name dynip.foobar.de.

### End configurable options

############################################################
if {$argc !=2} {
 puts "usage: [file tail $argv0] <ip-number> <servername>"
 exit 1
}       

set ip [lindex $argv 0]
set dns [lindex $argv 1]

# Now do the update
set nsupd [open "|nsupdate -v -y $update_key" r+]
puts $nsupd "server $dns"
puts $nsupd "update delete $name in a"
puts $nsupd "update add $name $TTL in a $ip\n"
# Achtung, die Leerzeile ist wichtig, sonst klappt das nicht
puts $nsupd ""
puts $nsupd "quit"
after 2000
close $nsupd
--schnapp--

Ergänzungen von Stefan

Da tcl nicht jedermanns Sache ist und man das eh von woanders aus aufrufen mag, habe ich zwei Scripte gebaut (eins auf dolly zum Updaten und eins auf meinem openwrt).
Das erste Script kapselt wie Svens TCL den nsupdate-Aufruf, nimmt aber die ssh-client-ip aus dem Environment, falls keine IP auf der Kommandozeile übergeben wurde:
Achtung, abhängig von den sshd-Einstellungen variiert das Format von $SSH_CLIENT. Siehe Script
doupdate.sh
#!/bin/bash

DIR=/home/stefan/dyndns
KEY=Kmaerkle.de.+157+63752.key
TEMPLATE=nsupdate.template
TMPFILE=/tmp/dyndns.file

IP=$1
if [ "${IP}x" = "x" ]; then
 # So gehts bei IPv6-Enabled sshd_config:
 #IP=`echo $SSH_CLIENT|awk '{print $1}' | awk -F':' '{print $4}'`
 # Reine IPv4 Adressen in der sshd_config:
 IP=`echo $SSH_CLIENT|awk '{print $1}'`
fi
 
if [ "${IP}x" = "x" ]; then
   echo "Error, no IP address found!"
else
   cat ${DIR}/${TEMPLATE} |sed s/##IP##/$IP/g  >${TMPFILE}
   nsupdate -k ${DIR}/${KEY} ${TMPFILE}
fi
       
Das Script benutzt ein Nsupdate-Template, das erscheint mir einfacher, als alles dynamisch zu machen:
nsupdate.template
server dns.gnuher.de
update delete ka.maerkle.de. in a
update add ka.maerkle.de. 300 in a ##IP##
send
Ich erlaube einem bestimmten ssh-Schlüssel nur, dieses Script auszuführen:
authorized_keys
ssh-dss AAAAB3....P5Z command="/home/stefan/dyndns/doupdate.sh"
Zu guter letzt habe ich auf dem OpenWRT ein Script laufen, das jede halbe Stunde überprüt, ob die vom Nameserver gelieferte IP mit der von ifconfig ausgelieferten übereinstimmt. Wenn nicht, dann wird das Script auf dolly angeschmissen:
updatens-cron.sh
#!/bin/sh
# Update IP Address File with current IP Address
EXTERNAL_IP= `ifconfig ppp0 | awk '/inet/ { print $2 }' | awk -F':' '{ print $2 }'`
KNOWN_AS=`nslookup ka.maerkle.de | tail -n 1 | awk '{ print $2 }'`
echo $EXTERNAL_IP
echo $KNOWN_AS

if [ $EXTERNAL_IP != $KNOWN_AS ]
then # If so update your Dynamic Host Record(s)
  echo Updating Nameserver ...
  /usr/bin/ssh -i /tmp/nsupkey stefan@dolly.gnuher.de "dyndns/doupdate.sh"
else
  echo nothing to do ...
fi

Das Script ist auf die Syntax des Busybox-NSLookup abgestimmt!

Kleine Bemerkung am Rande: will man mit dem OpenWRT-dropbear ssh per Key auf einen openssh-Server, muss man die Keys mit 'dropbearkey' erzeugen.