DNSSEC — the security extensions to the trusty Domain Name System (DNS) upon which almost all Internet transactions rely — is often considered hard to set up. My own setup has been very dated, using complicated scripts which needed to run after every change to the zone file. There was time to change this. Modern versions of the BIND make this rather easy, as I found out.
[Update 2024-11-10] This article is mainly here for historical reasons. For new setups, I recommend Knot DNS (and maybe dnstemple).
Background
DNSSEC extends DNS with security; namely authenticity. With proper authenticity, much more information can be stored there, such as which encryption key an authentic server for a particular domain is expected to present when establishing a connection. DANE (DNS-based Authentication of Named Entities), the mechanism that achieves this by adding TLSA (Transport Layer Security Authentication) records into DNS. But also other entries, such as ssh keys in SSHFP entries, or SPF and DKIM values should not be trusted unless stored in DNSSEC.
My old setup was based on running dnssec-signzone
as part of a regular script, together with some fancy include-file processing. This was not easy to set up and maintain. It was time to change this. Luckily, BIND has matured a lot in these years since manually creating my setup based on the HOW-TOs available at the time. Here is how to run DNSSEC today.
Activating DNSSEC today
Let me explain how one would do this today on Linux (the examples are from an Ubuntu installation). We assume there to be already an (unsigned) domain example.ch
with the following configuration entry in /etc/bind/named.conf.local
:
zone "example.ch" { type master; file "/etc/bind/example.ch.zone"; };
First, we need to move that file to /var/lib/bind/example.ch.zone
, and the configuration line updated to read as follows:[1]“dnssec-secure-to-insecure yes;
” is not required for normal operation, but is nice if you want to temporarily go back to an unsigned zone by issuing “nsupdate -l
⏎delete example.ch dnskey
⏎send
⏎quit
“, in case you want to try again. Update 2018-02-10: This DNSKEY
deletion procedure needs to be followed as well when importing a zone file which has already been manually signed before.
zone "example.ch" { type master; file "/var/lib/bind/example.ch.zone"; update-policy local; auto-dnssec maintain; dnssec-secure-to-insecure yes; };
This gives named
permission to perform it’s magic on the zone [2]the default apparmor
configuration for Ubuntu prevents named
from modifying anything in /etc/bind
, only in /var/lib/bind
(and /var/cache/bind
, meant for slave zones.
Next, we need to let named
know about DNSSEC. Add the following lines to /etc/bind/named.conf.options
, in the options {};
block, maybe right after dnssec-validation auto;
:
dnssec-enable yes; key-directory "/etc/bind/key";
Note that $INCLUDE
, $GENERATE
and similar statements in your zone files will be replaced by the contents they expanded to when signing was activated. Given that you now have dynamic updates available, this might obviate such statements anyway.
If you rely on including other dynamic files, this procedure is not for you!
[Update 2024-11-10] Knot DNS is much more flexible when it comes to inline signing and local updates.
Make sure you have a backup of these files, if you are unsure or they contain valuable data. It is good practice to put such files into a version management system such as subversion or git.
Adding -a RSASHA256 -b 2048
to the first dnssec-keygen
command below is commonly recommended; there are even DNS registars which will only accept that key type. If you have the option, I recommend using ECDSA by adding -a ECDSAP256SHA256
to this command, and, if your registrar supports it, also to the second command.[3]Update 2018-02-10: If you later need to change the encryption algorithm, please follow these instruction.
# mkdir /etc/bind/keys # cd /etc/bind/keys # dnssec-keygen -3 example.ch # Create the (short-term) key to sign the entries Generating key pair. Kexample.de.+013+64514 # dnssec-keygen -3 -fk example.ch # Create the (long-term) key to sign the above signing key Generating key pair.................................+++ ........+++ Kexample.de.+007+62928 # chown bind:bind * # Ensure they can be read by named # rndc loadkeys example.ch # Let BIND know about them # rndc signing -nsec3param 1 0 10 `od -Anone -tx4 -N4 /dev/urandom` example.ch # Enable NSEC3 and set a random mixing value ("salt") # rndc signing -list example.ch # Show signing status Done signing with key 62928/NSEC3RSASHA1 Done signing with key 64514/ECDSAP256SHA256
If you do not want NSEC3 or do not need it, you can also skip the rndc signing -nsec3param …
command above or undo it with rndc signing -nsec3param none
.
To fully enable DNSSEC, all there remains is to register the Zone Signing Key (ZSK, the one you created with -fk
above) with your DNS registrar. The information you need is in Kexample.de.+007+62928.key
, the file name printed as part of the key generation.
Be aware, that you have a dynamic zone now, i.e., any necessary changes are stored in the *.jnl file in the same directory. Changes to the *.zone file will be ignored. If you want to make modifications to the file, enclose the editing process in rndc freeze
/thaw
, as follows:
# rndc freeze example.ch # vi /var/lib/bind/example.ch.zone # Don't forget to increment the SOA serial! # rndc thaw example.ch
References
The following web pages provided inspiration for this article (the missing chmod provided ample reason for transpiration):
- The detailed information in the BIND documentation.
- The shorter article by DDI Guru on automatic zone signing
- I am also including advice by Olafur Gudmundsson.
- ISOC provides general instructions on DNSSEC and verification.
Instructions and caveats when you plan to change the DNSSEC algorithm used.