DNSSEC uses keys with which it signs DNS records, and there is a school of thought which suggests DNSSEC keys should be rolled (i.e. re-created) every once in a while. The recommended frequency for doing this is specified in DNSSEC Operational Practices, Version 2 with additional information in DNSSEC Key Rollover Timing Considerations (draft). Whether or not you want to roll keys is a matter of taste (and/or paranoia?). How often have you rolled your SSH host keys? (And I don't mean unplanned rolling by, say, re-installing the host without backing up and restoring its keys). How often has the root DNSSEC KSK key been rolled? Let's look at the root trust anchor which was published on the 15th of July 2010:

<?xml version="1.0" encoding="UTF-8"?>
<TrustAnchor id="AD42165F-3B1A-4778-8F42-D34A1D41FD93" source="http://data.iana.org/root-anchors/root-anchors.xml">
  <Zone>.</Zone>
  <KeyDigest id="Kjqmt7v" validFrom="2010-07-15T00:00:00+00:00">
    <KeyTag>19036</KeyTag>
    <Algorithm>8</Algorithm>
    <DigestType>2</DigestType>
    <Digest>49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5</Digest>
  </KeyDigest>
</TrustAnchor>

Now let us look at the current DS of the root's KSK:

dig @k.root-servers.net. . dnskey | grep 257 > root.dnskey
ldns-key2ds -n root.dnskey
.   172800   IN   DS   19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5

Notice a difference in the digest? No, I don't either. In other words, the root KSK has never been rolled, but ICANN is seeking volunteers for the DNSSEC Root KSK Rollover Plan Design Team...

The relationship between a DNSSEC-signed zone (e.g. example.org) and its parent zone (e.g. org) make rolling DNSSEC key-signing keys (KSK) difficult: when I renew keys for example.org I have to submit the public DNSKEY or its hashed DS record to the parent (org); they add / replace that record for my example.org in their zone and re-sign org creating a chain of trust from org to example.org. This of course means I can't just roll my KSK at will; if I don't interact with my zone's parent, my zone becomes insecure and thus bogus for validating resolvers. DNSSEC basically consists of islands of trust; keys in a zone which are validated by trust anchors in other zones; this is comparable to how delegation works.

In a test environment or in private DNS networks, DNSSEC is easy: I can create, change, roll, whatever DNSSEC KSK keys at my whim, copy the relevant DS records to parent zones, re-sign and all is fine. But can't this be automated?

RFC5011, Automated Updates of DNS Security (DNSSEC) Trust Anchors, specifies a mechanism by which trust anchors can be deployed automatically via the DNS. A resolver periodically queries the DNS to determine whether a new DNSKEY has been published; if so, and if it can be validated by an existing trust anchor, it's retrieved and used as a future trust anchor for that zone. RFC 5011 works because new keys are signed by old keys and thus the chain of trust is maintained.

Both the BIND and Unbound name servers support RFC 5011.

The upcoming version of OpenDNSSEC will also have support for RFC 5011. (If you're new to OpenDNSSEC, read an earlier post on it and I highly recommend you print out this excellent document created by AFNIC.)

What I basically do, is specify RFC 5011 for the KSK keys in my kasp.xml:

<KSK>
    <Algorithm length="4096">8</Algorithm>
    <Lifetime>P1Y</Lifetime>
    <Repository>SoftHSM</Repository>
    <Standby>0</Standby>
    <RFC5011/>
</KSK>

It's also important to note the following:

  • Your configured DelegationSignerSubmitCommand will not be invoked for RFC 5011 keys.
  • Keys jump from publish to active, bypassing the ready state.
  • The ds-seen command should not be invoked on these keys; in fact you probably won't see waiting for ds-seen as a status at all.

kasp2html

RFC 5011 support in OpenDNSSEC is very new and it is, in theory, difficult to test because of the waiting periods involved between rolls. The good folk at NLnetLabs chose to implement a feature which you compile in when building OpenDNSSEC and which you do not use in production! I can set an environment variable to define a particular point in time; with this, rolling a KSK becomes trivial:

$ ods-ksmutil key list
Zone:                           Keytype:      State:    Date of next transition:
jp.aa                           KSK           active    2019-01-15 21:49:34
jp.aa                           KSK           publish   2019-02-14 22:05:34
$ ENFORCER_TIMESHIFT="2019-02-14:22:05:35" ./sbin/ods-enforcerd -1 -d
WARNING: Timeshift mode detected, running once only!
Jan 20 09:42:47 deb ods-enforcerd: INFO: KSK has been rolled for jp.aa

So, how do I test this other than looking at the DNSKEY records published and signed by OpenDNSSEC in the zone?

test scenario

OpenDNSSEC signs a test zone (here: jp.aa) and notifies NSD which transfers the zone in and serves it authoritatively. On the other side I have Unbound and BIND configured as recursive, validating resolvers to answer incoming queries.

key-checker

A utility I've found very helpful in keeping track of keys as they are created and revoked is St├ęphane Bortzmeyer's key-checker which uses a small SQLite3 database to keep track of new keys. (Read the paper entitled Monitoring DNSSEC zones: what, how, and when?.)

I launch key-checker as

while true; do
    ./key-store-and-report.py jp.aa 172.16.153.112
    sleep 600
done

or via cron, etc. It probes the specified DNS server for DNSKEY records for the specified zone and mails me reports:

1  F Jan 20 [DNSSEC Check of my zones] New key 55503 in zone jp.aa.
2  F Jan 20 [DNSSEC Check of my zones] New key 26931 in zone jp.aa.
3  F Jan 20 [DNSSEC Check of my zones] New key 7921 in zone jp.aa.
4  F Jan 20 [DNSSEC Check of my zones] New key 16275 in zone jp.aa.
5  F Jan 20 [DNSSEC Check of my zones] New keyset in zone jp.aa.
Subject: [DNSSEC Check of my zones] New keyset in zone jp.aa.

    The keyset RC/faWBmRTBu+nZcCPuivXe6aGQ= appeared for the first time in the zone "jp.aa.".

    Its TTL is 300 and its members are: [55503, 26931, 7921, 16275]
Subject: [DNSSEC Check of my zones] New key 16275 in zone jp.aa.

        The key 16275 appeared for the first time in the zone "jp.aa.".

        Its flags are 385 and its algorithm 8.

I keep the reports in a mailbox and use that as an archive of what happened when.

Unbound

Unbound has a trust anchor configured which I obtained from ods-ksmutil key export --zone jp.aa --keytype ksk and placed in the file jp.anchor.

server:
    verbosity: 1
    logfile: ""
    username: ""
    chroot: ""
    root-hints: "/home/jpm/rfc5011/root.hints"
    auto-trust-anchor-file: "/home/jpm/rfc5011/jp.anchor"

remote-control:
    control-enable: yes

Some time after the successfull KSK rollover, Unbound successfully obtained the new anchor and stored it:

jp.aa.  300     IN      DNSKEY  257 3 8 AwEAA....; {id = 13759 (ksk), size = 4096b} ;;state=2 [  VALID  ] ;;count=0 ;;lastchange=1421830033 ;;Wed Jan 20 09:47:13 2015
jp.aa.  300     IN      DNSKEY  385 3 8 AwEAA....; {id = 52347 (ksk), size = 4096b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=1421830033 ;;Wed Jan 20 09:47:13 2015

Note how the comments show the REVOKED key; the key's flags (385) have bit 8 set which mean's it has been revoked.

BIND

Unfortunately, my experiments in doing the same for BIND haven't been particularly fruitful and I may now (a month later, on 2015-02-19) tell you that they culminated in CVE-2015-1349, so I will have to do this again. In theory, setting this up is just as easy as doing so for Unbound: I just configure a managed-keys stanza in named.conf, reconfigure, and that's it.

options {
    directory "/var/named";
    allow-query { any; };
    listen-on { 127.0.0.1; 172.16.153.110; };
    dnssec-enable yes;
    recursion yes;
    dnssec-validation yes;
    managed-keys-directory "/home/jpm/named";
};

managed-keys {
     "jp.aa."  initial-key 257 3 8
        "AwEAAcd8g/zOsovEQLmr/IM6Pvs3HQ9
         ...
         DrKO2DVOwe3MMzDy5L1ZJzSOH"; // {id = 52219 (ksk), size = 4096b}
};

zone "." in {
    type hint;
    file "/home/jpm/named/root.hints";
};

I'm too impatient: since I can't seem to be able to force BIND to "go, on, look now to see if there are new DNSKEYs, mate!", I have to wait until it does its thing. Also, I'm currently chasing down another little problem ...

20-Jan-2015 10:17:58.793 managed-keys-zone: Unable to fetch DNSKEY set 'jp.aa': failure

I have actually seen BIND write a revoked key (385) into managed-keys, but I haven't been able to yet actually test whether validation continues working. BIND operates as I expected it to after the rollover.

If you want to do your own experimenting with a "fake" DNS root zone which rolls its keys (currently every 90 minutes), Warren Kumari's Keyroller is what you need, and Jakob Schlyter has created an associated toolset which downloads the Keyroller key, formats it, and launches either BIND or Unbound on it.

Comments

blog comments powered by Disqus