# DNSSEC in the .nl zone mini HOWTO. The .nl.nl-experiment.



> published in 2003

# DNSSEC mini HOWTO
By Paul Wouters (paul@xtdnet.nl)

# Introduction
This article is a translation of the article "*Secure DNS, Het beveiligingen
van DNS in de praktijk* that appeared in
[C'T magazine](http://www.fnl.nl/ct/archief2003/ct2003-03/) on
March 14 2003.

# DNSSEC in the .nl zone
The Dutch NIC (SIDN [http://www.domain-registry.nl/]>),
The European Regional Internet Registry (RIPE<A
HREF="http://www.ripe.net/"></A>), and NLnetLabs<A
HREF=http://www.nlnetlabs.nl/></A> have created the first toplevel
secure DNS. The experiment is running its own set of nameservers to
guarantee that the experiment will not interfere with the production
nameservers. The project started in November of 2002 with the goal of
gaining experience in running DNSSEC for a TLD Registry.

For years, the IETF has been (re)designing the successor of the current DNS
system. The new protocols have been changed so often, people began to wonder
if it would ever happen at all. One would think that the DNS would have been
one of the first protocols to be thoroughly secured. After all, practically
all communication on the internet relies on the DNS. A malicious user only
needs to manipulate the DNS to get control of the communication.

![DNS zone file](/images/ctnl-dnssec-1.png)

*The standard DNS zonefile of the domain "ct.nl", with the standard
"start of authority" (SOA), nameserver (NS), mail (MX), address (A) and alias
(CNAME) resource records (RR's).*

# Digital Signature

Standard DNS queries and answers are easily faked. If third parties can observe
the DNS traffic of any machine between the enduser and the DNS server that person
is using, data can be easily manipulated. DNSSEC solves this problem
by using digital signatures for all records. A key-pair is generated,
of which the public key is put in the DNS itself, in the form of a KEY
record. The private key is then used to digitally sign all records,
including the public key record.  These signatures are placed in the SIG
records. A malicious user can still modify the DNS data, but without the private
key, the the corresponding SIG records cannot be recreated to validate the changed
records. The tampering will be noticed, and the spoofed DNS answers not believed.
The beauty of this setup is that the entire zone can be signed on a very secure
machine and then copied onto the nameserver. Even if one has full control of the
nameserver, one cannot change any DNS record without breaking the SIG record. An
attacker can ofcourse still destroy the nameserver, but at least no one will be
tricked to connect to an attacker's malicious network, even after a nameserver
compromise.

![ct.nl zonefile](/images/ctnl-dnssec-2.png)
    
*The ct.nl zonefile, secured with DNSSEC records.*
(KEY material shortened for readability).

DNSSEC has another new record type, the NXT record. This record
gives us the opportunity to deny the existence of a certain RR. It is not enough
to just *not* have a certain record to make it clear the requested RR doesn't exist.
We have to proof this somehow.

The NXT record for ct.nl shows the existence of the NS, SOA, MX, SIG, KEY and NXT
record types. It also tells us that the next RR, in alphabetical order,
is going to be www.ct.nl.  The NXT record of www.ct.nl shows that there
is only a CNAME, SIG and NXT record. And since its NXT record points
back to ct.nl, we know it is the last name in the chain. There is no
zzz.ct.nl. And all this information was digitally signed. This is the
essence of DNSSEC.

But we have a few wrinkles to iron out. The DNS is a hierarchical
system. The zone above our zone, the parent zone, has some information
about our zone. The nameserver of the parent zone contains nameserver
(NS) records to point to the responsible nameservers of its child zones.
And if the nameservers of the child zone themselves have names within
their own zone (for example when ns.ct.nl is an NS record for ct.nl),
then it also needs to pass that information to pass along as well ;
the so-called glue records.  If someone manages to manipulate those
records in our parent zone, then it doesn't matter how secure our own
server is. They will never reach our super-secure nameserver. So this
information needs to be signed as well.	 But our parent doesn't have
our private key, so it cannot sign those records on our behalf. Somehow,
we will need to give our parent some information about our key, without
turning it over.

# The Hint

Of course this problem isn't new to DNS. The .nl nameserver (ns.nic.nl)
already has NS records for our ct.nl zone. In our case these point
to ns.xtdnet.nl. However, this answer is given without setting the
so-called "authoritative answer" flag. The information is provided "as
is". If we would ask the same question to ns.xtdnet.nl, it would yield
the same answer, but this time the "authoritative answer" flag will be
set. If ns.xtdnet.nl would give different answer, we would call this a
"lame server".	But for DNSSEC, this hint is not enough. After all,
anyone can just claim to be an authoritative server. That is why DNSSEC
gives a cryptographic hint, the Delegation Signer(DS) record.

The DS record contains the id and the hash of the KEY record of the
child-zone.  The DS record itself is signed by the parent-zone with a
SIG record. To find the ct.nl zone we ask the .nl nameserver for
both the NS and DS records.  We receive a hint (NS) to use ns.xtdnet.nl
as nameserver and a hash of the key (DS) that as far as .nl knows, should
have signed the entire ct.nl zone. Then we go to ns.xtdnet.nl and ask for
the KEY record of ct.nl. We receive the KEY record, and the signature that
belongs to it. We hash the KEY and compare it with the hash in the DS record
we received from the .nl nameserver. If they match, we have securely landed
at the authoritative nameserver for ct.nl. and we can proceed to ask it
about the ct.nl domain. All the answers of ns.xtdnet.nl will be digitally signed,
and cannot be tampered with.

![secure resolving](/images/ctnl-dnssec-4.png)

*Securely resolving www.ct.nl, using the resolv tool made by Miek Gieben.*

# KEY roll-overs

However, with enough time and cpu-power, all crypto can be broken
eventually. That is why it is very important to change your KEY's
regularly. But we cannot just change the key, because then our
parent's DS record will be wrong. So how do we renew our KEY's
without constantly bugging the parent to update the DS record?

The trick is to use two KEY records in our zone, a zone-signing key
(ZSK) and a key-signing key (KSK). We sign all KEY records with the
KSK, then sign the entire zone with the ZSK. The KSK is the key for
which our parent publishes the DS record. The zone-signing key (ZSK)
can be relatively small (for instance 768 bits) if we recycle it every
month. We can keep the KSK for a year if we make it a bit stronger, for
example 2048 bit.

So we get the following path of trust: We trust the KEY
of .nl, and thus we trust the NS and DS that ns.nic.nl serves us which,
when used, ends us at ns.xtdnet.nl. We verify its KSK with the DS we got, so
we trust the KSK which has signed the ZSK, which has signed all the data
(RR's) of which we wanted to know the signed A record  www.ct.nl. And we
can now recycle the ZSK without notifying the parent. Though of course
we just postponed our problem. We still need to recycle the KSK after
a year, and we need to securely inform our parent about the new KSK.

To start a roll-over of the KSK we first create another KSK (let's call it
KSK2) and add this third KEY to the zone. Then we can inform the parent
(even insecurely!) that there is a new KSK. The parent checks whether
its existing KSK (for which it has a DS to verify) has signed the new
KSK2. If so, it will update its DS record to point to KSK2. Once we
are sure that no cached copies of KSK are scattered around the world,
we can remove KSK from our zone. For .nl, NLnetlabs has created such a
procedure, SECREG (Secure registration).

# From DNS to DNSSEC

Our last problem is that the world will not switch in a single moment
from DNS to DNSSEC. So while some subtrees, such as .nl, might have
switched, others, most notable the root zone (".") itself,  might still
be insecure. The resolve this issue, it is possible to define "secure
islands" within a insecure tree. You can define a 'trusted key' for a
particular tree. This is exactly what SIDN has done for .nl

We will now describe how to secure a .nl domain using DNSSEC and SECREG.
Obviously, the SECREG part only applies to .nl domains, but you can
still read the procedures involved in making any zone secure.

DNSSEC is still a fast moving target. The only software that can be
used to create signed zones at this time is the latest snapshot of bind9<A
HREF="ftp://ftp.isc.org:/isc/bind9/snapshots/bind-9.3.0s20021217.tar.gz"></A>.

In that snapshot, threading is broken, so you will need to
disable that with --disable-threads. Zones signed with the
snapshot can however be served by any recent nameserver software
package, such as the stable versions of bind8 and bind9 or nsd<A
HREF="http://www.nlnetlabs.nl/nsd/"></A>.  The only caveat is when
using bind8. If you setup a secure zone, with signatures that are
valid for a month, and you forget about your expeirment and let those
signatures expire, bind8 will remove the record from the zone. Bind9
will keep serving the expired record, and leave it up to the resolvers
querying it to determine whether or not to pass the expired record on
to the application.

To not jeopardize the regular operations of the .nl zone, two
separate DNSSEC aware CC:TLD nameservers, "bakbeest.sidnl.nl"
and "alpha.nlnetlabs.nl" are used. If you want to test secure
resolving, be sure to use those two servers instead of the official .nl
nameservers. Of course you can also use tools such as dig or resolv.pl<A
HREF="/projects/resolver/resolver.html"></A>
manually. If you wish to create your own secure recursing nameserver,
you need to run the latest bind9 snapshot and add a trusted-key statement
for the .nl key<A HREF="http://secreg.nlnetlabs.nl/key.shtml"></A>
in named.conf:

    trusted-keys {
    "nl." 256 3 1
    "AQOtBQXOH5L/wmOt01PuxXAfSk1bw/dneWPoCyl4yi8tLCjz+DkAs0mzAAvd9XUNpYDaf5KT
    ciSs9254oeiE0s0FuYbxS4nm7veZSPCgWoHULFNJtKPNeb4EEblNkAsEGagwQJoIrjlAYKx4C
    En3hPwElUlVko23I5tSSPPssxrVnQ==";
    };

(The above should be on a single line)

Be aware that using bind9 snapshots will often kill some of the
functionality of your nameserver. Do not run this on production servers,
unless you know what you're doing and have extensive monitoring enabled.
Even though the development is focused on dnssec, some snapshots also
broke normal resolving, so be careful. The next step is to install
Net::DNS::SEC from CPAN. Some of the perl scripts we use later on
depend on it. Olaf Kolkman of RIPE NCC has written a management-tool<A
HREF="http://www.ripe.net/disi/"></A> that uses it extensively. Such
a tool is vital once you start securing many zones. So after we have
installed all our software, we're ready to secure our domain, fnl.nl.
Ideally, this would be the time to remove the signing machine from the
network, and only connect it to upload the signed zones to the primary
nameserver. Other methods would be even better, such as transferring the
zones with a USB pen-drive. The security setup of the signer machine is
left as exercise for the reader.

We will start by creating the KSK and ZSK:

    $ dnssec-keygen -a RSASHA1 -b 2048 -n ZONE fnl.nl
    Kfnl.nl.+005+16217
    $ nssec-keygen -a RSASHA1 -b 768 -n ZONE fnl.nl
    Kfnl.nl.+005+25541

The private keys are in the files with extension .private. The public
keys are in the files with extension .key. If you are creating a large
amount of keys, you might need to use "-r /dev/urandom". This random
source is slightly less secure, but will not block while you're waiting
for new randomness to appear. It seems that, with Linux at least, the
quickest way of getting more random is to move the mouse.
Once we're done with the key-pair creation, we add the KEY records to
the zonefile:

    $ cat *key >> /var/named/fnl.nl

And after we've increased the zone's serial number, we're ready to sign the zone:

    $ dnssec-signzone -o fnl.nl -k Kfnl.nl.+005+16217.key /var/named/fnl.nl Kfnl.nl.+005+25541.key

We can then copy the zonefile to our primary nameserver and reload the zone:

    # rndc reload fnl.nl

(If you use RedHat, you can also use 'service named restart')

After a few minutes, your secondary nameservers should also have loaded
the new zone. We will use the dig command to verify this. We recommend
that people who are used to using the nslookup or the host command really
break that habit by now. If you preferred the output of host or nslookup
over the output of dig, you can now use the +multiline option to dig
(which you can even put in a .digrc file) to get output that is very
similar to nslookup or host.  To verify if our secondary server received
the new zone, we query a key record:

    $ dig +dnssec +multiline -t key fnl.nl @ns.xtdnet.nl

We should receive an answer that contains both a KEY and a SIG record. Also
take a close look at the "flags" section of the dig output. The Authoritative
Answer (aa) flag will say whether or not the nameserver itself was responsible
for the zone (authoritative). The Authenticated Data (ad) flag tells us whether
our answer was verifiably secure using the dnssec extensions. The above query,
contrary to what you might except, did not set the "ad" flag. The reason
for this is that the verification of data is done by a resolver, and not by
the authoritative server itself. It wouldn't make much sense to verify the
zone on your own disk.

# Creating the DS record

When we have our secure zones loaded on our nameservers, we can
ask SECREG to vouch for our domainname and request it adds a signed DS record to
the .nl zone. We can  request this through email (for bulk registrations) or use
the web-interface<A HREF="http://secreg.nlnetlabs.nl/"></A>:

![selecting keys](/images/ctnl-dnssec-6s.png)

*Selecting the correct KEY for SECREG.*

At this point there is no way that SECREG can determine which key is
your ZSK and which is your KSK, though a draft to make a distinction is
on its way. If you used a different key-size when generating the keys,
you can tell the keys apart by their size. If you used an equal size,
you'll have to check your key id, which is apparent from the filename
it uses.  Once you've told SECREG which key is the KSK, the zone will
appear as "processing".

![SECREG requests](/images/ctnl-dnssec-7s.png)

*Registrant and Registrar have two days to cancel the SECREG request.*

SECREG decided to add a two day waiting period so that any involved party (Registrant
or Registrar) has a chance to decline the request. This is an experimental policy,
that might develope into a Best Current Practice ("BCP").
If no one declines the request, your zone will be added to SECREG.  The .nl zone is
refreshed every weekday between 7am and 11am. This 40 MByte file is then signed by
the signing machine, currently a Pentium-III 1Ghz. This process takes about two hours,
and when it is done, the file size has grown to 300 Mbyte. SECREG will send emails to
the parties involved if it has successfully added a zone, which means adding and signing
the DS record for your zone.

![AD flag on DNS answers](/images/ctnl-dnssec-5.png)

*The "ad" flag is set. Dig has successfully found the address of our
website using DNSSEC.*

# KSK roll-over

The KSK and ZSK do not have an expire date - only SIG records expire.
The ZSK roll-over can be done whenever you want, since the KSK will just
sign whatever ZSK you have. So this rollover just consists of deleting
the old key, generating a new one, and updating the KEY record in the
zone.

The KSK rollover needs to happen in a co-ordinated fashion
with the parent, so that the DS record can be updated. First, one needs
to create a new KSK:

    $ dnssec-keygen -a RSASHA1 -b 2048 -n ZONE fnl.nl
    Kfnl.nl.+005+16310

The public KEY record needs to be added to the zone. Assuming the zonefile
lives in /var/named/fnl.nl, issue:

    $ cat Kfnl.nl.+005+16310.key >> /var/named/fnl.nl

And after we increased the serial, both KSK's need to sign the KEY
records and the ZSK needs to sign the entire zone: 

    $ dnssec-signzone -o fnl.nl -k Kfnl.nl.+005+16217 -k Kfnl.nl.+005+16310
     /var/named/fnl.nl Kfnl.nl.+005+25541

Then we need to propagate the new zone to the primary and secondary
nameservers.  Then we go back to the SECREG website and choose
"rollover". It will present us with a TXT record containing a random
challenge string. This needs to be signed using the sign.pl tool linked
on that page, using the OLD KSK. 

    $ sign.pl
    What is the full path to your private key? []
    Kfnl.nl.+005+16217.private
    What is your domain? []
    fnl.nl
    Record to sign: []
    3600 IN TXT "random txt m80fN0LtmpXz2aQ"

    Key path       : Kfnl.nl.+005+35861.private
    Domain name    : fnl.nl
    Record to sign : 3600 IN TXT "random txt m80fN0LtmpXz2aQ"

    Is this correct (y/n)? y

    fnl.nl.	 3600	 IN	SIG	TXT  5	2  3600	 20030315125047 (
			    20030213125047 35861  fnl.nl
			    KHR718ehTtidLkTUbnf+NPPJymSo2jwrWTkPOvjKySFTe
			    v6tRoCPkvQ2pZxnn7aR3hOCrMAWmwa7WCUJ4GzdPJD2fx
			    M0zYkH722ewhVmayyZTTgGQ81cpVmbag/95/OR )

![siging](/images/ctnl-dnssec-8s.png)

*Using the sign.pl tool and our old KSK, we have signed the random TXT
record as proof that are allowed to do a KSK roll-over.*

If the signature is correct, SECREG knows we are the holder of the old
KSK key, and that we are authorized to perform a key roll-over. SECREG
will update the DS record, which will be published when the .nl zone
gets reloaded. Our roll-over is complete.

The old KSK might still be in various caches on the net, so you should at
least keep it for as long as its TTL was. Only when that time has past,
can the old KSK be removed from the zone.  Olaf Kolkman's maintenance
tool does an excellent job of managing these roll-overs.

# Conclusion

The Netherlands is the first TLD with a functional DNSSEC registry. One
cannot expect to find many programs <A HREF=http://www.dnssec.net></A>
that already use the extra functionality that DNSSEC offers. Because of
the many changes, even very recently, of the DNSSEC protocol, this hasn't
really been possible so far. DNSSEC extensions are also missing from the
POSIX libraries, such as the C-library, which means that every program
which wants to support DNSSEC needs to write their own dns functions. The
first applications to adopt DNSSEC will likely be FreeS/WAN, the most widely
deployed Linux IPsec implementation, and OpenSSH. Both tools use public key cryptography,
and need to fetch and verify their own application keys. These keys can be
put into the DNS, but one can only rely on it if the DNS itself is secure.
And the entire situation can become quite complex, as soon as DNSSEC finds it
way into DHCP client updates, dynamic dns updates or IPsec opportunistic encryption.
And hopefully browsers will also soon understand DNSSEC, so that online
banking can implement real DNS security, instead of advising the user
"to only continue when the name of our bank appears in the address bar".
We have been waiting for DNSSEC for years. Let's hope the Dutch SECREG
experiment gives everyone a push in the right direction.

<A HREF="http://www.gnu.org/licenses/fdl.html">Copyright (c)  2003</A>
> Permission is granted to copy, distribute and/or modify this document
> under the terms of the GNU Free Documentation License, Version 1.2
> or any later version published by the Free Software Foundation;
> with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.

