Inklings: a tumblelog

How I manage domain zones signed with DNSSEC

Given I’m setting up a domain, I’d might as well document some of the process. These notes are rough, and I may have missed something. I’ll be going over the process to correct any issues. This doesn’t cover the process of setting up OpenDNSSEC and nsd initially.

Here’s the layout of /usr/local/etc/nsd on my server, lir:

-rw-r--r--  1 nsd   wheel  1544 31 Jul 12:10 nsd.conf
-rw-r--r--  1 root  wheel  8120 22 Sep 15:18 nsd.conf.sample
-rw-------  1 nsd   wheel  1277 30 Jan  2014 nsd_control.key
-rw-------  1 nsd   wheel   790 30 Jan  2014 nsd_control.pem
-rw-------  1 nsd   wheel  1277 30 Jan  2014 nsd_server.key
-rw-------  1 nsd   wheel   782 30 Jan  2014 nsd_server.pem
-rw-------  1 nsd   wheel   461  2 Apr  2015 secrets.conf
-rw-r--r--  1 nsd   wheel   247  1 Jul 13:56 slave-zones.conf
drwxr-xr-x  2 nsd   wheel  1536  6 Feb  2015 zones/
-rw-r--r--  1 nsd   wheel  1918  6 Feb  2015 zones.conf

I don’t keep everything in the one file. Rather, I separate out my zone list into zones.conf, any slave zones I’m hosting for others into slave-zones.conf, and I keep the zone transfer keys in secrets.conf.

To keep complexity down, I use patterns. This means that I can collect together all the settings for any set of zones into one place, which makes managing zones, if you’ve more than just a few, much easier. That’s one of the reasons why my zones.conf file is so small.

The zones directory mostly contains symlinks into two directories, /usr/local/var/opendnssec/signed and /usr/local/var/opendnssec/unsigned. The former contains files generated by OpenDNSSEC, and the latter is a git repo containing the unsigned zones. The latter also contains a file called rebuild.sh, which rebuilds the zones.conf list. Here’s what it looks like:

#!/bin/sh

ODS_ROOT=/usr/local/var/opendnssec
NSD_ZONES=/usr/local/etc/nsd/zones

get_zones () {
    # Unsigned zones have the lowest priority, so we link them first.
    find $ODS_ROOT/unsigned -depth 1 -type f \
        -and ! \( -name README.md -or -name .gitignore -or -name rebuild.sh \)
    # Then we link signed zones, which will overwrite the links for any
    # unsigned zones.
    find $ODS_ROOT/signed -depth 1 -type f
}

write_zone () {
    cat <<EOZ
zone:
    name: "$1"
    include-pattern: "master"
EOZ
}

get_zones | while read zone; do
    ln -s -f $zone $NSD_ZONES/$(basename $zone).zone
done

for zonefile in $NSD_ZONES/*; do
    if test -L $zonefile; then
        write_zone $(basename $zonefile .zone)
    fi
done > $NSD_ZONES/../zones.conf

The nice thing is that if there are two files with the same name in signed and unsigned, then the one in signed with trump the one in unsigned.

So, that’s the layout, now let’s configure a zone. I’m adding the zone cíat.eu, which is an IDN, so the file name is actually xn–cat-rma.eu. Adding the zone is as simple as this:

sudo ods-ksmutil zone add --zone xn--cat-rma.eu

That will add the file with that name in /usr/local/var/opendnssec/unsigned to the database and update the zonelist.xml file. Now run:

sudo ods-ksmutil update zonelist

Which should result in the configuration for the signer daemon being written out. When you list your keys, you should see that it’s been published:

$ sudo ods-ksmutil key list --zone xn--cat-rma.eu
Keys:
Zone:                           Keytype:      State:    Date of next transition:
xn--cat-rma.eu                  KSK           publish   2015-10-21 04:10:44
xn--cat-rma.eu                  ZSK           active    2016-01-18 14:10:44

You can’t push the key or delegation signer (DS) record up to the registry just yet. Rather, you have to wait until the date given for the key until it’s safe to publish the key or DS record with the registry. In this case, we have to wait until ‘2015-10-21 04:10:44’ before the key or DS record can be published. This is to give time for the signed zone to propagate so you won’t end up with weird issues where a resolver is seeing that a zone should be signed, but the cached copy they have hasn’t yet been signed.

Now, you can publish the zone. For this, I run my rebuild.sh script, which rebuilds my zones.conf file. You could do it manually, or use the script I gave above to automate the process. Once that’s done, nsd needs to be notified to reload the zone:

% sudo nsd-control reload xn--cat-rma.eu

The zone should now be published and start propagating.

When the state of the KSK transitions, you can then publish the DS record or public key with the registry to establish the chain of trust.