Domain Name System Security Extensions (DNSSEC) enable the validation of DNS responses by authenticating the communication between DNS servers. This means that users can trust that the DNS responses they receive match the contents of the authoritative zone file.
This post is a quick step-by-step introductory to deploying DNSSEC.
In this tutorial, we will be using BIND on an Ubuntu Server. We will be using the following zone information:
Zone name/domain: irrashai.net
Zone file: db.irrashai.net
Note: At the time of writing, BIND 9.10.x has reached End-of-Life (EOL). It is recommended you use the current stable versions (BIND 9.12.4-P1 or BIND 9.14.1). For the purposes of this tutorial, we will keep using v9.10.3 since Ubuntu ships with it by default — the command and syntax should be the same.
Part 1: DNSSEC validation for end-users
This is for end-users, service providers and anyone running a recursive or caching resolver.
- Enable DNSSEC
Open /etc/bind/named.conf.options and add:dnssec-enable yes; dnssec-validation auto;
Note that dnssec-enable is already set by default, and you may choose not to explicitly add it in the config.
If dnssec-validation is set to auto, it defaults to the DNS root zone as the trust anchor. BIND includes a copy of the root key which is kept up to date automatically. If set to yes, a trust anchor must be explicitly configured using the managed-keys or trusted-keys option.
- Test if it is validating
Using the dig command:dig @localhost www.apnic.net
You can replace www.apnic.net with the signed domain.
dig @localhost www.apnic.net +dnssec +multiline ; <<>> DiG 9.10.3-P4-Ubuntu <<>> @localhost www.apnic.net +dnssec +multiline ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53884 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;www.apnic.net. IN A ;; ANSWER SECTION: www.apnic.net. 300 IN CNAME www.apnic.net.cdn.cloudflare.net. www.apnic.net. 300 IN RRSIG CNAME 8 3 300 ( 20190608045355 20190509035355 43023 apnic.net. oX8qHhFXJLyu3TKru/1sGrDZnnyq3+aI2zhIFk6IF6PK nTXrzFE/USOjDffJI5+x3QAzPzBKDKXB1+XaXHq1lgw9 Mw6i3mx+NTkjfq7m1bN/wbZD8ddzjY1GK4lrZ/zM39WL 5GQ+2ryIMY0aQFdQzufnHkGHMlqJM6fbHdREwPY= ) www.apnic.net.cdn.cloudflare.net. 300 IN A 104.20.22.173 www.apnic.net.cdn.cloudflare.net. 300 IN A 104.20.36.173 www.apnic.net.cdn.cloudflare.net. 300 IN RRSIG A 13 6 300 ( 20190510112012 20190508092012 34505 cloudflare.net. jJT6w0CRI6AMMagUdBT7XIMk/7Phr1kpUGdQdh7RhLPz dJdT3SF0lTKQ0oawaTuSyQjp3Zkwluo3J7/+SnwcHw== ) ;; Query time: 2705 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Thu May 09 20:20:12 AEST 2019 ;; MSG SIZE rcvd: 396
Notice that every answer has a corresponding signature (RRSIG record.)
A validated response should have the AD (Authenticated Data) bit flag set and the header will have the status: NOERROR.
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47652 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
A response that is not validated will not have AD bit flag set and the HEADER status will be SERVFAIL.
;; >>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 21978 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
Part 2: DNSSEC signing for domain owners
This is usually for registries and hosting providers, or any user who owns a domain.
2.1 Generate key pair for ZSK and KSK
First, let’s generate the Zone Signing Key (ZSK). The syntax is as follows:
dnssec-keygen -a <ALGORITHM> -b <BITS> -n ZONE <ZONENAME>
Replace ALGORITHM, BITS, and ZONENAME. If not specified, the default values are RSASHA1 for the algorithm (-a), and a keysize (-b) of 1024 for ZSK and 2048 for KSK.
For the examples, let’s use irrashai.net as our zone. If you want to keep this default, the command will simply be:
dnssec-keygen irrashai.net
If you plan to run this in a test environment, make sure to add source of randomness (-r). Otherwise, it will take a long time to generate the keys.
Let’s use a more secure algorithm and longer bits to generate ZSK. The command will be as follows:
dnssec-keygen -r /dev/urandom -a RSASHA256 -b 1024 -n ZONE irrashai.net
Here’s the expected output:
dnssec-keygen -r /dev/urandom -a RSASHA256 -b 1024 -n ZONE irrashai.net Generating key pair..................++++++ .......++++++ Kirrashai.net.+008+1245
Optional: If you choose to use elliptic curve for the algorithm, the ‘-b’ option is not necessary.
dnssec-keygen -r /dev/urandom -a ECDSAP256SHA256 irrashai.net.
Next, we generate the Key Signing Key (KSK). The command is very much the same, with a couple of adjustments:
- Specify that it’s the KSK
- Increase the key size.
dnssec-keygen -r /dev/urandom -a RSASHA256 -b 2048 -fKSK -n ZONE irrashai.net Generating key pair....+++ .+++ Kirrashai.net.+008+50539
$ more Kirrashai.net.+008+50539.key ; This is a key-signing key, keyid 50539, for irrashai.net. ; Created: 20190509104232 (Thu May 9 20:42:32 2019) ; Publish: 20190509104232 (Thu May 9 20:42:32 2019) ; Activate: 20190509104232 (Thu May 9 20:42:32 2019) irrashai.net. IN DNSKEY 257 3 8 AwEAAarP/lL9Qt2zqFX/NHKBsX2EVZBx8oMIFw/ON8ij5sIpZyIvgLxR aoH/TdJiw8Y9WkXlCSr0IGHM3kooE OsTgC+FBD0sZqCTxQW1tQQLgkHS /4tyglSihcuyC5mL8N77I1BqgHnou3eBeJV0rNogTHs5tkP0Ed4j98pc vBPtpekMHyftbucK8E0JWKfhahZqebS5N rKp56YueaNc9w31jslTh7xM pMKlwSLIrNB28fcP1/azPcvF7rFhYJuwk1iFOime4LUdVxTY/UCSPi+m pd4iuEUskoraHMsmbN+jj+orNEMjxNoKeBZoX hwcHPJ09scnhSTAKtjA fovltMH2WM0=
You should now have four files in the directory. One key pair (.key and .private) for the ZSK and another pair for the KSK.
Note: There are two possible keys to use for KSK — RSASHA256 and ECDSAP256SHA256. We have used the first one for this guide. Otherwise, ECDSAP256SHA256 is the recommended value.
2.2. Signing the zones
BIND supports three methods for signing zones: manual signing, auto-dnssec, and inline signing. We will look at both manual and automated options.
- Manual signing
Manual zone signing is done using the dnssec-signzone command.
Let’s first examine the content of the keyfiles.ls -alh /etc/bind/keys/ more /etc/bind/keys/Kirrashai.net.+008+57241.key
Notice the format of the file name is K<zonename>.+<algorithm-number>+<keyid>.key
The .key file is the public key. Copy or reference the public keys for ZSK and KSK into your zone file. Let’s include the public DNSKEY in the zone file as follows:
vi db.irrashai.net
$INCLUDE “keys/Kirrashai.net.+008+03966.key” #myzsk $INCLUDE “keys/Kirrashai.net.+008+40765.key” #myksk
Now we can sign the zone using the secret keys. Here is the syntax:
dnssec-signzone -o <zonename> -N INCREMENT -t -k <KSK> <zonefile> <ZSK>
For our example, the command should be:
dnssec-signzone -o irrashai.net -N INCREMENT -t -k Kirrashai.net.+008+40765db.irrashai.net \ Kirrashai.net.+008+03966
This generates a file db.irrashai.net.signed with the signed data. If you wish to name it something else, use the -f flag.
Examine this signed file. Notice that the file is bigger and now contains new records created after signing (RRSIG, DNSKEY, NSEC).
Next is publishing the zone. Reconfigure BIND to load the signed zonefile.
To do this, edit the configuration file and point to the signed zone.
vi named.conf.local
zone “irrashai.net.” { type master; #file “db.irrashai.net”; file “db.irrashai.net.signed”; };
- Automatic signing
The other method is using automatic signing. Update the configuration as follows to add the last three lines:vi named.conf.local
zone “irrashai.net.” { type master; file “/etc/bind/db.irrashai.net”; key-directory “/etc/bind/keys”; auto-dnssec maintain; inline-signing yes; };
Note: The key-directory is the location of the KSK/ZSK keys. The BIND user must have ‘read’ access to this, so update your permissions accordingly.
auto-dnssec has two options — allow or maintain.
- auto-dnssec allow searches the key directory and signs the zone with the corresponding keys once it receives the command rndc sign.
- auto-dnssec maintain does as above but also periodically checks the key directory.
Using Remote Name Daemon Control (RNDC), we can then apply the updated config done above, and load the keys from the given directory.
rndc reload rndc reconfig rndc loadkeys irrashai.net
Then sign the zone using the following command:
rndc signing -list irrashai.net
2.3: Chain of trust
To establish the chain of trust, we will then need to update the parent zone with the hash of our public key. This is called the Delegation Signer (DS).
If you used manual signing in Part 2.2, then the DS record should already be generated. Check for the two files starting with dsset-<xxx>. That should contain the two DS records that should be sent to your upstream.
If you used automatic signing, you will have to generate the DS record using the following command:
dig @localhost dnskey irrashai.net | dnssec-dsfromkey -f – irrashai.net
Then send the DS records to your parent zone. The parent zone (usually your hosting provider) generally has a portal where this can be uploaded. For reverse DNS, this can be done by updating the domain whois object using MyAPNIC.
2.4: Guard against zone walking with NSEC3
The steps above generate NSEC records. NSEC has been known to be susceptible to ‘zone walking’ attacks. That is, an attacker can find all the information in your zone by ‘walking’ it. NSEC3 provides a solution which makes it really hard (but not impossible) to do this attack.
So, for this section, let’s redo Parts 1 to 3, but instead using NSEC3. The update commands are as follows:
First, generate keys.
dnssec-keygen -r /dev/urandom -a RSASHA256 -3 -b 1024 -n ZONE irrashai.net dnssec-keygen -r /dev/urandom -f KSK -a RSASHA256 -b 2048 -3 -n ZONE irrashai.net
Then randomly generate a number up to 2^31 and represent as 8 Hexadecimal digits. This is your salt.
openssl rand -hex 4
Load the keys and sign them.
rndc loadkeys irrashai.net rndc signing -NSEC3PARAM 1 0 10 <some-salt> irrashai.net.
Get the DS record.
dig @localhost dnskey irrashai.net | dnssec-dsfromkey -f – irrashai.net
Finally, upload to your parent zone.
Learn more via our webinar
There’s more to DNSSEC that we are unable to discuss in here (like key re-signing and rollover). To learn more, attend the free APNIC Academy DNSSEC Webinar.
For the complete reference on configuring DNSSEC in BIND, see ISC’s guide [PDF 2.2MB].
The views expressed by the authors of this blog are their own and do not necessarily reflect the views of APNIC. Please note a Code of Conduct applies to this blog.
I’m using Ubuntu 18.04. Then Part 1 is wrong. Not the file /etc/bind/named.conf.local should be altered, but the file /etc/bind/named.conf.options In that file is allready the dnssec-validation auto; line, and you should put the line dnssec-enable yes; above that one. Thanks for the info.
rndc reload
rndc reconfig
rndc loadkeys irrashai.net
I cant make “rncd loadkeys” work on Ubuntu 18.04.
Even when running as root you’ll get the error rndc: ‘loadkeys’ failed: permission denied
Skipping those 3 rndc lines above and using 1 line containing e.g. “rndc reload example.com” gives the feedback “zone reload up-to-date” so i guess that does the trick.
And users need to open port 53 and 953 on UFW and their routers for the UDP/TCP protocol.
Hi, i want updated information on all the latest training information/new letters
this is obsolute. dnssec-enabled yes; <– does not exist anymore, grandpa.
Hello everyone. I tried to write a script to automate DNSSEC configuration. But I have troubles including keys in files.
#sudo echo “\$INCLUDE /etc/bind/K$nom_zone.*.key” >>/etc/bind/db.$nom_zone
#sudo echo “\$INCLUDE /etc/bind/K$nom_inv.*.key” >>/etc/bind/db.$nom_inv
#sudo chown root:bind $key_zone1
#sudo chown root:bind $key_zone2
#sudo chown root:bind $key_inv1
#sudo chown root:bind $key_inv2
sudo mv $key_zone1.key zone_ksk.key
sudo mv $key_inv1.key inv_ksk.key
sudo mv $key_inv2.key inv_zsk.key
sudo mv $key_zone2.key zone_zsk.key
#sudo chown root:bind K$nom_zone.*.key
#sudo chown root:bind K$nom_inv.*.key
sudo echo “$INCLUDE $INCLUDE zone_ksk.key” >> /etc/bind/db.$nom_zone
sudo echo “$INCLUDE $INCLUDE zone_zsk.key” >> /etc/bind/db.$nom_zone
#sudo echo $key_zone2 >> /etc/bind/db.$nom_zone
sudo echo “$INCLUDE $INCLUDE inv_ksk.key” >> /etc/bind/db.$nom_inv
sudo echo “$INCLUDE $INCLUDE inv_zsk.key” >> /etc/bind/db.$nom_inv
#sudo echo $key_inv2 >> /etc/bind/db.$nom_inv
Here are some ways I used to include keys inside files. But none of these worked.
Who can help me find a solution