Actions: | Security

AllGoodBits.org

Navigation: Home | Services | Tools | Articles | Other

Practical Dynamic DNS

Like many people, I have machines that receive IP addresses via DHCP; for example, my home ISP provides me a dynamic address. I want to be able to reach those machines by name using DNS.

Therefore, I set up Dynamic DNS so that when the IP address of the external interface of my home router changes, my server's DNS configuration is automatically updated, using Dynamic DNS (ddns).

There are 2 parts to this process:

  1. configuring the server to allow dynamic dns updates.
  2. configuring the home router to notice when its IP address changes and sending the ddns update.

Receiving Dynamic DNS using using bind9

Create a keypair

dnssec-keygen(8) will create keys that can be used to grant access to the DNS zone to be updated. Look at the manpage for details, but for our use case all we need is:

dnssec-keygen -a HMAC-MD5 -b 512 -n USER me.example.com.

This command creates 2 files, one with the suffix '.private' and the other with the suffix '.key'.

The private key goes on the client and the public key goes on the server.

Configure the BIND server

We need to create a stanza for the key in named.conf (or in some file included by named.conf):

key me.example.com. {
     algorithm "HMAC-MD5";
     secret "53rm41snsdmJ5==";
     };

We need to allow that key to update the zone in question, so we need to modify that zone's stanza in the named.conf:

zone "example.com" {
    type master;
    file "example.com.db";
    allow-transfer {
          slaves;
    };
    allow-update {
          key me.example.com.;
    };

This will allow the key to have full access to update the zone 'example.com'. You might want to grant more restricted access in which case you should investigate update-policy. Here's an example to allow our key to update the A record for the same name(grant <key> <type> <zone> <record-types>):

zone "example.com" {
    type master;
    file "example.com.db";
    allow-transfer {
          slaves;
    };
    update-policy {
            grant me.example.com. name me.example.com. A;
    };

DHCP client config

Many dhcp clients will have a mechanism to run arbitrary scripts when certain DHCP events occur, such as binding a new IP address. The event 'BOUND' is defined as "The DHCP client has done an initial binding to a new address".

nsupdate(1) is a tool that is distributed with BIND that can submit updates to BIND.

dhcpcd

In order to 'hook into DHCP events', dhcpcd can run scripts. Various OS distributions will include their own, although you can specify. On the system I'm looking, at the script /lib/dhcpcd/dhcpcd-run-hooks runs scripts in the directory /lib/dhcpcd/dhcpcd-hooks. All I need to do is put a script in that directory. The script itself is just a invocation of nsupdate, see below:

PRIV='/etc/bind/Kme.example.com.+foo+bar.private'
REQ=/etc/bind/ddns-update-request

IP=`ip addr show eth1 | grep inet | cut -d' ' -f 6|sed 's/\/.*$//'`

cat <<EOF > ${REQ}
server bind.example.com
zone example.com
update delete home.example.com. A
update add home.example.com. 86400 A ${IP}
show
send
EOF

case "${reason}" in
     BOUND|TEST)      nsupdate -k ${PRIV} -v ${REQ} ;;
     esac

dhclient

The same script can be used, although it must be executable and therefore needs a shebang line.