One important maintenance requirement for DNSSEC is the key rollover of the zone signing key (ZSK). With this procedure a new public/private key pair is used for signing the resource records, of course without any problems for the end user, i.e., no falsified signatures, etc.
In fact it is really simply to rollover the ZSK with BIND. It is almost one single CLI command to generate a new key with certain time ranges. BIND will use the correct keys at the appropriate time automatically. Here we go:
Some Prenotes
It’s all about timing! A new ZSK must be present in the zone before (!) it signs resource records. Likewise it should remain in the zone even after it is not used anymore for some time.
The DNSSEC keys have four main dates stored within them, which are the following:
- Publish: The time at which the key is public available in the zone
- Activate: From this time on it is used to sign RRs
- Inactive: No longer used to sign
- Delete: Removed from the zone
The later on used CLI commands have the following options to specify these dates: -P, -A, -I, and -D, exactly matching the first letter of the descriptions above.
Let’s have a look at a common key rollover timing, i.e., a pre-publish phase of 1 month, while an active time of 3 months, followed by one more month (inactive) before it is deleted:
Note that a new key is published in the last month of the active phase from the predecessor key. This enables all DNS resolvers to see the new key before it is actively used to sign data.
Time values are specified either discrete or with an offset: “Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a ‘+’ or ‘-‘, it is interpreted as an offset from the present time. For convenience, if such an offset is followed by one of the suffixes ‘y’, ‘mo’, ‘w’, ‘d’, ‘h’, or ‘mi’, then the offset is computed in years (defined as 365 24-hour days, ignoring leap years), months (defined as 30 24-hour days), weeks, days, hours, or minutes, respectively. Without a suffix, the offset is computed in seconds. To unset a date, use ‘none’.” (From the dnssec-settime manual.) Also note that all time values are in UTC!
dnssec-settime
To command line tool dnssec-settime changes dates of existing keys. In a common scenario you have never rotated your ZSK before. That is: it has no inactive nor delete time set. But to rollover to a new ZSK (created later), the inactive and delete dates must be set. Use the -I and -D options on the existing ZSK key pair, e.g., to set the inactive date 4 month from now, while the delete date to 5 month from now:
1 |
dnssec-settime -I +4mo -D +5mo <key> |
For example, I started with these values for my first ZSK from weberdns.de and “cat”ted the result. Note the activate and inactive dates:
1 2 3 4 5 6 7 8 9 10 11 12 |
weberjoh@jw-vm16-ns0:/etc/bind/keys$ sudo dnssec-settime -I +4mo -D +5mo Kweberdns.de.+008+57909 dnssec-settime: warning: Permissions on the file ./Kweberdns.de.+008+57909.private have changed from 0640 to 0600 as a result of this operation. ./Kweberdns.de.+008+57909.key ./Kweberdns.de.+008+57909.private weberjoh@jw-vm16-ns0:/etc/bind/keys$ cat Kweberdns.de.+008+57909.key ; This is a zone-signing key, keyid 57909, for weberdns.de. ; Created: 20160205194924 (Fri Feb 5 20:49:24 2016) ; Publish: 20160205194924 (Fri Feb 5 20:49:24 2016) ; Activate: 20160205194924 (Fri Feb 5 20:49:24 2016) ; Inactive: 20161001134524 (Sat Oct 1 15:45:24 2016) ; Delete: 20161031134524 (Mon Oct 31 14:45:24 2016) weberdns.de. IN DNSKEY 256 3 8 AwEAAc1G9dfFSBL+/NxRd7//80J8Hx8hjUyaQ7oaJV0tOErEc1+To0BG p3FOB7fQFQ6dJIHzfRD4YO0KoJjaH4P7fWO6Qs+05U6dnf2BGPy91m/4 LHqM+6jzFMMf566GHxuZYB/8OkKcyRU7IS+vubtYL8jT7hqzqg+XXpQb DRlbtNgP |
That was the first step. Now let’s continue with the creation of new ZSKs:
dnssec-keygen -S
As in the first post about DNSSEC signing, dnssec-keygen is used to create the keys. It has the great “-S <key>” option, described as: “Create a new key which is an explicit successor to an existing key. The name, algorithm, size, and type of the key will be set to match the existing key. The activation date of the new key will be set to the inactivation date of the existing one. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days.” That is: referring to the last key, only the inactive and delete dates must be set to generate a new key, the publish and activate dates are set automatically. If using the “ZSK rollover every 3 month” approach while starting in 4 month from now on with the activation (due to inactivation of the first key with dnssec-settime), the -I and -D values must be incremented by 3, starting with 7 and 8:
1 2 3 |
weberjoh@jw-vm16-ns0:/etc/bind/keys$ sudo dnssec-keygen -S Kweberdns.de.+008+57909 -I +7mo -D +8mo -r /dev/urandom Generating key pair.....++++++ ....................++++++ Kweberdns.de.+008+26703 |
That is: this new key
- will be published in 3 months (that is: 1 month before the first key is “inactive”),
- used in 4 month (because the first key is inactive in 4 month),
- inactive in 7 month (set with -I, –> after the usage of 3 months), and
- deleted in 8 month (set with -D, –> 1 month after inactive).
Refer to the timeline figure shown above. ;) It helps!
And then keep on going creating new keys, each one using for 3 month, i.e., increment the I and D times by 3 such as:
1 2 3 |
sudo dnssec-keygen -S Kweberdns.de.+008+26703 -I +10mo -D +11mo sudo dnssec-keygen -S Kweberdns.de.+008+41295 -I +13mo -D +14mo sudo dnssec-keygen -S Kweberdns.de.+008+61119 -I +16mo -D +17mo |
Create as much keys as you want, e.g., for 2-3 years. But NOTE: For the last key you are creating, don’t use the -I and -D options to have a lifetime of forever. This avoids the situation in which no key can be active anymore which would result in falsified (or even no) DNS signatures.
1 |
sudo dnssec-keygen -S Kweberdns.de.+008+07401 |
You should add a big reminder to your calendar to generate more keys when the old ones are inactive!
The files must be readable by bind, so I adjusted the ownership with:
1 |
sudo chown bind:bind * |
The final step is to reload the keys for the zone:
1 |
sudo rndc loadkeys weberdns.de |
Watch out the syslog entries whether BIND accepts and uses them, such as:
1 2 3 |
Sep 1 16:11:20 jw-vm16-ns0 named[1720]: received control channel command 'loadkeys weberdns.de' Sep 1 16:11:20 jw-vm16-ns0 named[1720]: zone weberdns.de/IN (signed): reconfiguring zone keys Sep 1 16:11:20 jw-vm16-ns0 named[1720]: zone weberdns.de/IN (signed): next key event: 01-Sep-2016 17:11:20.248 |
That’s it.
Examples
The following DNSViz graphs and dig listings show the process during my key rollover for weberdns.de. Refer to the descriptions below the graphs for more details:
The same is true if querying the dnskeys with dig. For example, the following listing only shows the first ZSK with id = 57909:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
weberjoh@jw-nb12-lx:~$ dig weberdns.de dnskey +multi ; <<>> DiG 9.10.3-P4-Ubuntu <<>> weberdns.de dnskey +multi ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54400 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;weberdns.de. IN DNSKEY ;; ANSWER SECTION: weberdns.de. 3591 IN DNSKEY 257 3 8 ( AwEAAdQXI+UfqnGbHdwJtBBStf0CM8Q8nXcriaOysrpG EDNkM//amUBD2YMWQ3g+htca6tmzfDJMM5D0gOk5d4Id EmdywkcH+0rGLjNiNEPFnZUpwb6XsYD+ZI/WEuSlp+KC EV8vwELq7VltABrFT+9Rz5CEvokTxonzQrvnfclVHaGw O7cglgALsFqJCqBpvDZvEr2Z6dSepjDnFC9BPS6V8PGS NwAYEtzDp/lrQojkCj28xHj2OCjpr0dIQjdjGFJTHIlc 9cYTAHjdPDsC8Eqfs5HcL3ruU6cbqjTn+5Lm4RdXpOWV gemVvIGDnUN+v+Tma/WgtQk7U3saizNJ3epCv3s= ) ; KSK; alg = RSASHA256; key id = 63202 weberdns.de. 3591 IN DNSKEY 256 3 8 ( AwEAAc1G9dfFSBL+/NxRd7//80J8Hx8hjUyaQ7oaJV0t OErEc1+To0BGp3FOB7fQFQ6dJIHzfRD4YO0KoJjaH4P7 fWO6Qs+05U6dnf2BGPy91m/4LHqM+6jzFMMf566GHxuZ YB/8OkKcyRU7IS+vubtYL8jT7hqzqg+XXpQbDRlbtNgP ) ; ZSK; alg = RSASHA256; key id = 57909 ;; Query time: 1 msec ;; SERVER: 192.168.120.22#53(192.168.120.22) ;; WHEN: Thu Sep 01 16:35:25 CEST 2016 ;; MSG SIZE rcvd: 464 |
While a few days later the next ZSK with id = 26703 was published:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
weberjoh@jw-nb12-lx:~$ dig weberdns.de dnskey +multi ; <<>> DiG 9.10.3-P4-Ubuntu <<>> weberdns.de dnskey +multi ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54177 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;weberdns.de. IN DNSKEY ;; ANSWER SECTION: weberdns.de. 3600 IN DNSKEY 257 3 8 ( AwEAAdQXI+UfqnGbHdwJtBBStf0CM8Q8nXcriaOysrpG EDNkM//amUBD2YMWQ3g+htca6tmzfDJMM5D0gOk5d4Id EmdywkcH+0rGLjNiNEPFnZUpwb6XsYD+ZI/WEuSlp+KC EV8vwELq7VltABrFT+9Rz5CEvokTxonzQrvnfclVHaGw O7cglgALsFqJCqBpvDZvEr2Z6dSepjDnFC9BPS6V8PGS NwAYEtzDp/lrQojkCj28xHj2OCjpr0dIQjdjGFJTHIlc 9cYTAHjdPDsC8Eqfs5HcL3ruU6cbqjTn+5Lm4RdXpOWV gemVvIGDnUN+v+Tma/WgtQk7U3saizNJ3epCv3s= ) ; KSK; alg = RSASHA256; key id = 63202 weberdns.de. 3600 IN DNSKEY 256 3 8 ( AwEAAdAeTdXab14Qp3A8YjQUhu2DSkJwWC6X6Y8V4O34 UiRAxfXb3Z3zYIeMntyQIgSXrIiY60WW532O21borUfS SReundoZiyq/GBLsPtXL1iQeLXT4QWWg9w2fg3y7Xde5 gzTswXazRIgMX8lqttmfIuZuU9qnWi2OoUCR5Pm2/rdj ) ; ZSK; alg = RSASHA256; key id = 26703 weberdns.de. 3600 IN DNSKEY 256 3 8 ( AwEAAc1G9dfFSBL+/NxRd7//80J8Hx8hjUyaQ7oaJV0t OErEc1+To0BGp3FOB7fQFQ6dJIHzfRD4YO0KoJjaH4P7 fWO6Qs+05U6dnf2BGPy91m/4LHqM+6jzFMMf566GHxuZ YB/8OkKcyRU7IS+vubtYL8jT7hqzqg+XXpQbDRlbtNgP ) ; ZSK; alg = RSASHA256; key id = 57909 ;; Query time: 21 msec ;; SERVER: 192.168.120.22#53(192.168.120.22) ;; WHEN: Sun Sep 04 23:22:17 CEST 2016 ;; MSG SIZE rcvd: 612 |
How Often?
How often should you rollover your ZSK? Well, it depends. The “use your ZSK for 3 month” opinion is quite conservative from my point of view. We are talking about 2048 bit crypto! This is used within TLS certificates that stay on the Internet for a couple of years.
You should rollover your ZSK on a regular basis to be prepared if your private key got lost. That is: to never rollover your keys is not a good advise. To my mind a good compromise is to rollover the ZSK every 6 month or 12 month. With this regularity you will practise key rollovers at least once a year while you have not that much burden.
Featured image: “Keys” by Rosa Say is licensed under CC BY-NC-ND 2.0.
This is by far the best explanation of key rollovers I have read. Thank you.
What about KSK rollover? 2048 bit is not too bad, but maybe every 1-2 years?
Could you do a tutorial on that too, by any chance?
Yes, you are absolutely correct. The KSK rollover is still missing on my blog. I am working on it. ;)
Have a look at this opensource project for automated rollover (cron). https://github.com/northox/dnssec-reverb
This is an incredibly useful post. Thanks so much!
Now that newer forms of BIND include dnssec-keymgr, most of this too has been automated, with the exception of updating the DS record with your domain registrar.