DNSSEC algorithm-rollover with simple scripts

Posted in Security with tags dnssec -

Finally I’ve found some time to transition my DNSSEC setup to a new algorithm. It took a lot of research, reading and finding the right tools. It appears that still everyone is using automated setups, which means nobody knows what is going on anymore when you’re talking nitty-gritty details on DNSSEC.

As an example: there is a lot of discussion of people saying that the KSK/ZSK setup is not necessary anymore, certainly not with ECDSA. But there is no example of it anywhere on how to actually run a domain with a single key. Using OpenINTEL we found that the number of CSK situations is roughly 5% in the Netherlands, and around 1-2% for zones like .net, .com and .org. Note, this percentage is of DNSSEC domains, not all domains.

Here’s what I’ve done on moving my zone over to a single key ECDSA P-256 with SHA256, also known as Algorithm 13 in DNSSEC.
The tooling that I’ve used is the LDNS toolkit extended with my own signzone script and ldns-mergezone. All very simple tools that operate on text-based zone files and should work with any kind of DNS server.

Summary of the procedure

The global reasoning behind the methodology below is to prevent inconsistencies in DNS caches. This is why you first add new signatures without any key information. They can exist harmlessly alongside the old signatures. A strict reading of the RFCs require that signatures exist in every algorithm in DNSKEY records. Some older resolvers do this strict reading and may treat your entire zone as bogus if they encounter an algorithm without the corresponding signatures. This can possibly happen in certain cached situations.

This is why, once the current TTL runs out you are sure that the signatures exist everywhere, you can add the key information. Again, alongside the old signatures, so that the old key still works. At that point you have a zone that is valid by both the old key as well as the new key. Then you switch upstream to the new key. Once you’re happy that it works, the final step is that you remove the old key and then the old signatures. Again, to prevent a situation where there could be a key without the corresponding signatures.

If you want to verify your steps during the process, I recommend DNSviz.net or DNSSEC-debugger.

Initial step

Prepare the change in DNS, lower the TTL of your DNS zone. Depending on how fast you want to move you can lower to 5 minutes (600) or 1 hour (3600). In NSD the TTL is written as the number just after the RR type.

I moved the original keys and zonefile into a new directory “oldalgo”. Run a “signzone.sh” operation on it to make sure there is a new version number. The end result in this folder is only that you have a new SOA version number.

# signzone.sh oldalgo/1sand0s.nl.zone

Create a new directory “newalgo” with a copy of the same original zone file (with the old SOA) and generate a new key. We generate this key as a “KSK”, because that means the SEP flag is set. The flag value will be 257, but we can just use it to sign the entire zone.

# ldns-keygen -k -a ECDSAP256SHA256 1sand0s.nl

The zonefile in this directory must be edited so that the zone also contains the DNSKEY records of the oldalgo.

# egrep "IN[[:space:]]+DNSKEY" oldalgo/1sand0s.nl.zone.signed >> newalgo/1sand0s.nl.zone
# signzone.sh newalgo/1sand0s.nl.zone

Then as the first step of the transition you want to introduce the new signatures, without introducing a new key. The old signatures will be there as well. The oldalgo and newalgo zones should both have the same SOA version number. Then we use the ldns-mergezone utility to do the merging in the proper way for the first step.

# ldns-mergezone -f oldalgo/1sand0s.nl.zone.signed -t newalgo/1sand0s.nl.zone.signed -1 -o 1sand0s.nl.zone.signed
# nsd-control reload

The resulting situation in DNSviz should look like something like this (the yellow flags are a warning for the time being too close to the current):

Introducing the new DNSKEY record

In the second step we’re introducing the new DNSKEY, which will be signed by both keys. This means we’re editing the zones in the oldalgo folder:

# egrep "IN[[:space:]]+DNSKEY" newalgo/1sand0s.nl.zone.signed >> oldalgo/1sand0s.nl.zone
# signzone.sh oldalgo/1sand0s.nl.zone
# signzone.sh newalgo/1sand0s.nl.zone
# ldns-mergezone -f oldalgo/1sand0s.nl.zone.signed -t newalgo/1sand0s.nl.zone.signed -2 -o 1sand0s.nl.zone.signed
# nsd-control reload

The result is a zone that is signed by both the oldalgo and the newalgo (RRSIG), containing the identifiers (DNSKEY) of both keys. The trust boundary is still with the original key.

This results in a slightly updated picture at DNSviz showing that the new key is distributed with the zone:

Switching over to the new DNSKEY

We wait the TTL of your own zone to make sure that everyone has this new DNSKEY record. Make a record of the DS key that currently exists for your zone for safekeeping should something go wrong. Now we can change the DS record at your registrar to point to the new key. Depending on your registrar you may need to provide your own DS record, or just enter the keytag and the public key.

# ldns-key2ds newalgo/K1sand0s.nl.+013+45114.key
# less newalgo/K1sand0s.nl.+013+45114.ds
1sand0s.nl. 3600 IN DS 45114 13 2 0c29a394d7f5eae8088d29eff3ef3113bdf9b9456d27f78af0dde48c7a122e02

Once you’ve changed the new key information at your registrar, you have to wait until the upstream zone does an update, depending on the upstream this can take up to an hour.

In this stage, if you did something wrong, you can just switch back to the old DS record, by changing it back to point to the old key. Everything will go back to the old situation as soon as the upstream updates again. Should everything have gone correctly, it will look something like this:

Transition to the new situation

Everything should now be in order, the new RRSIGs have been distributed and the new DNSKEY record is known everywhere. Final ingredient is that the upstream DNS server also points to the new DNSKEY. The only thing left to do is to clean up. To be careful we remove the DNSKEY entries first, and the old signatures later. First edit the newzone and remove all the DNSKEY records, then go ahead as follows:

# vim 1sand0s.nl.zone # remove all the DNSKEY records
# signzone.sh oldalgo/1sand0s.nl.zone
# signzone.sh newalgo/1sand0s.nl.zone
# ldns-mergezone -f oldalgo/1sand0s.nl.zone.signed -t newalgo/1sand0s.nl.zone.signed -3 -o 1sand0s.nl.zone.signed
# nsd-control reload

Finally to the new production situation

Finally, once another TTL has expired you can go to the new production situation with just one (new) algorithm in the signed zone.

# cp newalgo/* .
# signzone.sh newalgo/1sand0s.nl.zone

The proper zone and just the single new key will be in this directory, so the zone can now be signed using the signzone script, which will introduce the proper DNSKEY record again.

And you’re done!

Written by