I've been following Dirk
Eddelbuettel's dramas with his broadband
IP address changing (but hey, they don't call it a dynamic IP address
for nothing), and I thought I would write about how I survive on a dynamic
IP address. Until I moved house and had an outage of a few weeks of my
broadband, I
had changelogs.debian.net hosted on
the back of my broadband connection without any major problems using this
method.
I've been using ADSL since around 2000, and always been on a dynamic IP
address. I had previously enjoyed a static IP address on my dialup
connection back in the good old
days (gee our web design sucked back then).
I have had daedalus.andrew.net.au since around the same time I went
broadband. It has always been sitting in a colo facility somewhere, so is
subsequently on a static IP address, and it acts as the primary nameserver
for my domains.
For secondary DNS, I use a mixture of a free account I have
with UltraDNS (from back in the days
when it was Secondary.COM), and the member service provided by SAGE-AU.
So my ADSL IP address changes from time to time. My ADSL connection usually
drops out and reconnects every 7 to 10 days, usually coming back with a
different IP address. I like to maintain home.andrew.net.au pointing at it,
so that I can SSH into it from elsewhere.
So in the way of DNS zone files, I have andrew.net.au, which has everything
in it, and I have a subdomain (an actual bonafide subdomain in its own zone
file) called dyn.andrew.net.au. (I'll explain why in a moment, it's
technically not necessary, but convenient to do so). home.andrew.net.au is a
CNAME to caesar.dyn.andrew.net.au, and this is the DNS record that I update
whenever my ADSL connection "redials".
My ADSL connection is PPPoE, so I use the
Roaring
Penguin PPPoE software, which just works with pppd. pppd allows
you to run arbitrary scripts when the link comes up, so I've written a Perl
script to send a signed (TSIG) DNS update request to my nameserver, and dropped
it in /etc/ppp/ip-up.d/
You have to go for a signed request because the update is coming from
dynamic address space. I guess I could have added a huge ACL to my BIND
configuration allowing all of the address space for my ISP to be able to
send my nameserver dynamic updates, but that's a bit broad for my liking. So
instead, I have:
zone "dyn.andrew.net.au" {
type master;
file "/etc/bind/master/dyn.andrew.net.au.zone";
allow-update {
key zoneupdatekey;
};
allow-transfer {
203.27.221.52;
131.170.24.210;
};
};
I then create a key with
dnssec-keygen -a HMAC-MD5 -b 512 -n ZONE dyn.andrew.net.au
This produces a couple of files like Kdyn.andrew.net.au.+157+43730.key and
Kdyn.andrew.net.au.+157+43730.private, which strangely enough seem to
contain the same key material, despite one supposedly being private.
I add the key material to a key directive in my named.conf:
key zoneupdatekey {
algorithm hmac-md5;
secret "iBHthjiMEM3gqPaQy1oME9sTp87awUU65s+z9Rd9s3wxfE1BpTzfM0j/qSGKCxfDECKvVxOLyxQP459JAx5IfA==";
};
(and no, this is a key I generated for the purposes of this blog entry, not my
actual key)
This key is also in my script, as is the domain that is being updating, and
that is it. The script can be tested by hand by invoking it:
PPP_IFACE=ppp0 PPP_LOCAL=127.0.0.1 /etc/ppp/ip-up.d/dyndns
and this should set the IP address to 127.0.0.1 for the A record in question.
The script logs to /var/log/messages on the box it is run on, and
/var/log/daemon on the box running BIND will contain some information about how
the update request was handled.
caesar.dyn.andrew.net.au has a 5 minute TTL, so the most anyone with a
self-respecting caching nameserver should retain the old IP address for when it
changes is about 5 minutes. That's good enough for me.
Why did I bother with the whole subdomain thing? The BIND 9 Administrator
Reference Manual says that you shouldn't edit a dynamic zone file by hand,
so you really don't want to mix a zone file that has manually maintained
entries with stuff that is updated dynamically. Also, BIND tends to make a bit
of a mess of the zone file, so I give it its own zone file to make a mess of,
and never touch it myself.
So in summary, home.andrew.net.au is a CNAME to caesar.dyn.andrew.net.au, which
is updated dynamically via my script. My script is just a Perl implementation
of something you could do with nsupdate and a few lines of shell, by the way.