Implementing DNSSEC


DNS is on of the most basic and needed database structures on the planet. Its’ hierarchical, and goes from top to bottom.
If you have no clue on how DNS works, you should check out this fine tutorial over at Once you did that, come back here and we talk security. But seriously, read that. Now.

The issue

Like I said (and you read, if you haven’t: shame on you!) DNS is hierarchical, top-to-bottom approach. And spoofing or tampering can happen in any level, even at the bottom (dns server hijacking).

Enter DNS-SEC.

Basically you trust the Root DNS Server (paranoid users: stop reading here: There be no hope for yee!). The next level down, most likely the registries have a secret key and a public key. They propagate the public key to the upper level, in this case the root DNS Server). Any answers from the registries dns server are now signed, and the signature (which is done with the private part of the key) must match the public key that is provided by the upper level (root zone dns).

This goes on-and-on down to the final nameserver: yours (or mine). Its result is now also signed with its private key, that must match the public key from the registry; which again in turn is signed by the private key of the registry, which in turn again must match the public key provided by the root nameserver. And ultimately you trust the root nameserver, that’s why the root servers dns key is self-signed. A final answer from my nameserver looks like this:

;; ANSWER SECTION:        2966    IN    A        2966    IN    RRSIG    A 7 2 3600 20160619151322 20160520143736 32345 AVR[...]vis=

Notice the new record type RRSIG? This resource record signature is the before-mentioned signature. And your dig command now lists an additional flag:

;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

the ‘ad’ means authenticated data, marking a trusted reply (from top top bottom).
Jealous? Let’s get you trusted, then!

Whacking at bind

I am assuming you are using the powerhouse of the dns world: isc’s bind. There are others out there, but meh.
Like I said, you trust the DNS root servers. So the first step is to get the current dns signing key by using dig:

~ $  dig . dnskey

; <<>> DiG 9.10.3-P4-Ubuntu <<>> . dnskey
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41517
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 13, ADDITIONAL: 20

; EDNS: version: 0, flags:; udp: 4096
;.                IN    DNSKEY

.            164824    IN    DNSKEY    256 3 8 AwEAAarQO0FTE/l6LEKFlZllJIwXuLGd3q5d8S8NH+ntOeIMN81A5wAI 18g3u9w/esNkThwgXTEa2mX1iOPdTcl3yRleAExxF22lEU2E0GKY2XdY r/BxP5fojJAPRgtEGDl72NSwSnD2/a8uPNirAJZoab36Hlw41QxEl7bm Co0280mt
.            164824    IN    DNSKEY    257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq QxA+Uk1ihz0=

The last two lines contain the DNSKEY, you might have noticed the, umm, dnskey ressource record type. On your nameserver, go into your configuration directory for bind, for me (Centos 7) it’s “/etc/bind”, create a file named ‘’ and copy & paste the  “DNSKEY 257” line in there, save that.

Verify what you did:

# Success:
[ns1 ~]# dnssec-dsfromkey -2 -f  .
. IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32 F24E8FB5

# Fail:
[ns1 ~]# dnssec-dsfromkey -2 -f  .
dnssec-dsfromkey: warning: unknown RR type '[junk]'
dnssec-dsfromkey: fatal: can't load unknown class/type

If you do not get the success message you did something wrong with copy & paste; recheck. Moving on.

Edit the file named.conf.options (create if it does not exist), add:

trusted-keys {
  . 257 3 8 

options {
  dnssec-validation yes;
  dnssec-enable     yes;

The trusted-keys part is the trusted anchor you dig’ed earlier on and what you pasted into the file. Strictly it’s not needed to split the keys into multiple files, but for the sake of tidiness I’ll always do it.

Once you restart bin it’s prepared to sign and query dnssec signed zones. But we want our zones to be signed. Moving on!

Preparing our zones

We need to create private and public keys for our zones. As we are totally paranoid, we go nuts on the encryption. This slows down dns lookup but only in theory. I have not seen any measurable slowdown in the wild so far. Let’s get cracking.
Inside the bind configuration directory, create a keys directory, cd in it:

[ns1 bind]# cd /etc/bind
[ns1 bind]# mkdir keys
[ns1 bind]# cd keys/
[ns1 keys]#

Awesome job. Now let’s actually create the keys:

# dnssec-keygen -K /etc/puppet/modules/dns/files/keys -a NSEC3RSASHA1 -3 -b 4096 -n ZONE -r /dev/random
Generating key pair....................................................................................................................................................................................................................++ ...........................................................................++
# ls -lha /etc/puppet/modules/dns/files/keys
total 16K
drwxr-xr-x 2 root   root   4.0K Aug 13 10:48 .
drwxr-xr-x 4 puppet puppet 4.0K Aug 13 10:47 ..
-rw-r--r-- 1 root   root    954 Aug 13 10:48
-rw------- 1 root   root   3.3K Aug 13 10:48
# dnssec-keygen -K /etc/puppet/modules/dns/files/keys -a NSEC3RSASHA1 -3 -b 4096 -f KSK -r /dev/random
# ls -lha /etc/puppet/modules/dns/files/keys
total 32K
-rw-r--r-- 1 root   root    953 Aug 13 12:38
-rw------- 1 root   root   3.3K Aug 13 12:38
-rw-r----- 1 puppet puppet  954 Aug 13 12:33
-rw-r----- 1 puppet puppet 3.3K Aug 13 12:33

Replace ‘’ with your domain. Parameters used:

  • -a: encryption used (algprithm). Possible values: RSA, RSAMD5, DSA, RSASHA1, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512, ECCGOST, DH, HMAC-MD5, HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384, and HMAC-SHA512.
    Note: Not only you, but also your registry must support your chosen encryption method. And all clients out there.
  • -b key size. Totally depends on your encryption used.
  • -3: use NSEC3-capable algorithm
  • -n is the type of key, in this case ZONE for the zone-keys and KSK for keys-signing-keys.

Now, make the zone a dnssec-zone, edit ‘named.conf.local’, add the bold line to your domain:

zone "" {
    type master;
    file "/etc/named/zones/";
    update-policy local;
    auto-dnssec maintain;
    key-directory "/etc/named/keys";

The ‘auto-dnssec’ is what makes magic happen. The following setting are allowed:

allow - permits keys to be updated and the zone to be re-signed whenever the user issues the rndc sign zonename command.
maintain - includes the functionality above, but will also automatically adjust the zone's DNSSEC keys according to DNSSEC key timing metadata that is supplied. 
create - includes the above, but signals named to create new DNSSEC keys when needed. (NOTE: this option is not yet implemented; the syntax has been reserved for future use.)
off - which disables automatic DNSSEC functionality

As we have both zone keys and key-signing-keys we can publish the ksk-key to the root-zone (registry) and use that key to sign our zone-key for shorter-lived zone-keys. This increases security without the hassle of pushing the new public key to the registry. And ‘maintain’ does all that for us. For the love of all that is holy: keep it at maintain.


So far we did:

  1. Trust the root-dns key and added it as anchor to our DNS Server,
  2. We enabled dns-sec inside the server for outgoing queries,
  3. Created both zone keys and key signing keys for (each) zone(s),
  4. Introduced said keys to our server and
  5. Made our server auto-sign our zones with the keys.

Restart your server, and do a ‘dig +DNSSEC +trace’. Your server will answer with the ‘RRSIG’ that we wanted. At this point, your server is prepared and already handing out RSSIG to everyone who asks. The downside is that no one will authenticate your because your public key is not yet parked at your registry.

Informing the People

The one thing I really can’t help you with is the exact way to publish your keys to your registry as every registry does it in a different way. It all does, however, boil down to supplying these things:

  • Your DNSKEY, that in one of those .key-files, the one with “DNSKEY 257” in it.
  • They will ask your about “flag“. As we publish the KSK (type 257) and not the zone-key (type 256), enter 257.
  • If you used “-a NSEC3RSASHA1” and “-3” above, tell them Protocol ‘3’.
  • Algorithm, same as above, ‘3’.

Once you submited those informations to your registry (mostly done via a fancy web-gui), wait a day or so for them to update their servers. Once that is done, check your setup with dns-viz, example output should look like mine. Sorry about not being able to really help you navigating your registry.


… enjoy your secured resolution!


Touched base with Linux back in 1995, got hooked up on it ever since. I am using Linux for both private and office for two decades. Working as a System Administrator at a medium sized hosting company I get in touch with all kinds of trouble. All of which can be solved with Linux. In my blog I am sharing solutions to problems that I had to search for myself in hope that someone else out there might find them useful.

Leave a Reply

Your email address will not be published. Required fields are marked *