Table of Contents
THIS IS A WORK IN PROGRESS AND WILL CONTAIN ERRORS! Please email me about the inevitable mistakes.
DNSSEC-bis is the latest, and arguably, best attempt at providing authenticated DNS records with guaranteed integrity. The author of this article has not been known for his kind words on DNSSEC, yet has promised an honest look into the state of the art of DNSSEC-bis.
It is amazing what good company, some free food and drinks will do!
Below you will find explained all concepts of DNSSEC-bis in a way that furthers understanding. To really get down to details it is suggested to read the RFCs and the Best Current Practices documents, as well as Olaf's HOWTO.
This document is aimed at complete DNSSEC beginners (like me), but does presume some knowledge of signatures and keys.
Don't be afraid when I say I am a complete beginner - I routinely document stuff to gain an understanding. See for example the Lex-Yacc HOWTO or SIMD and other techniques for fast numerical programming with gcc
The need for improving DNS security is obvious. A well-prepared attacker stands a good chance of spoofing in modified answers as unmodified DNS relies on a 16-bit 'secret' for matching answers to questions. Furthermore, nameservers have been known to have their cache poisoned with 'bad' data.
In this document you and I are going to discover if DNSSEC is able to improve the security of DNS without making things unworkably complicated. This is by no means certain to the author, so it is going to be an interesting ride.
This document contains no original work and is based solely on the RFCs above, edited by Roy Arends, Rob Austein, Matt Larson, D. Massey, and S. Rose. Furthermore, the DNSSEC HOWTO by Olaf Kolkman is a great source of information, as is as the operational practices document by the same author, linked below.
Peter Koch of DENIC got me interested in DNSSEC again, so thanks are due to him as well.
Quoting from RFC 4033:
The Domain Name System Security Extensions (DNSSEC) add data origin authentication and data integrity to the Domain Name System.
The really interesting bit is that DNSSEC strives to do so using the current nearly unmodified DNS protocol, including caching, wildcards, forwarders etc. This is a massive challenge.
Compare an HTTP proxy, like squid, which makes no attempt to cache encrypted HTTPS data. When accessing HTTPS through a proxy, a direct connection is made through the proxy to the origin webserver.
DNSSEC in contrast attempts to preserve authentication and integrity even through caches. This is possible because DNSSEC does not guarantee exclusivity, it does not actually encrypt data.
But it is a massive challenge nonetheless.
The first step is obvious: sign records, and make sure the signature and the record itself are both cached, and delivered with answers. This is just like what happens when you add a PGP signature to an email message.
To this goal, DNSSEC has invented the RRSIG record type, the Resource Record Signature, and it is indeed sent with answers, it looks like this:
a.z.w.example. 3600 IN MX 1 ai.example. a.z.w.example. 3600 RRSIG MX 5 2 3600 20040509183619 ( 20040409183619 38519 example. OMK8rAZlepfzLWW75Dxd63jy2wswESzxDKG2 f9AMN1CytCd10cYISAxfAdvXSZ7xujKAtPbc tvOQ2ofO7AZJ+d01EeeQTVBPq4/6KCWhqe2X TjnkVLNvvhnc0u28aoSsG0+4InvkkOHknKxw 4kX18MMR34i8lC36SR5xBni8vHI= )
This is the MX record of
a.z.w.example, which points to 'ai.example', followed by its signature.
You can see in the RRSIG that this is a signature of the MX record of a.z.w.example.com, that the
signature algorithm is number '5'.
The next number we'll address later - it has to do with wildcards. I think this example, lifted from the RFC, is wrong btw.
The next number is the original TTL, followed by the expiry of the signature (20040509183619), followed by the date this signature was generated (20040409183619).
The next number, 38519, is the 'tag' if the key used to generate this signature. This is needed because there might be more keys available to sign records.
The next label, 'example.' is the owner of the key used to sign this record, which should be equal to the name of the zone containing the record.
This all then is followed by the actual base64 encoded signature of all the above.
We've seen how we can sign a DNS record, but that leaves the important question of where to get, and more importantly, how to trust the key used to sign.
We'll start out simple by describing the DNSKEY record, which as the name implies, contains a key, or in fact the public part of an asymmetrical key.
example.com. 86400 IN DNSKEY 256 3 5 ( AQPSKmynfzW4kyBv015MUG2DeIQ3 Cbl+BBZH4b/0PY1kxkmvHjcZc8no kfzj31GajIQKY+5CptLr3buXA10h WqTkF7H6RfoRqXQeogmMHfpftf6z Mv1LyBUgia7za6ZEzOJBOztyvhjL 742iU/TpPSEDhm2SNKLijfUppn1U aNvv4w== )
This specifies the
example.com key. 256 means that his is a 'Zone Key', 3 is there to
signify the protocol version and must always be 3. The next number, 5, is one we saw earlier, and
it denotes the algorithms used. This is then followed by the actual key.
Note that the key tag, 38519 in the previous example, is hidden in the base-64 encoded key. There are tools available that add the tag as a comment to the zone.
This is all fine, but can we trust this key? We can query the key from the
but as long as we get both the key and the signature over the same network, no real security is being
There are two interesting ways out of this dilemma. One is to retrieve the key using unspecified out-of-band means, like via a PGP signed message, or via ssh to a trusted host. That key can then become an 'anchor' for you.
The second way is to have an existing 'anchor' sign your keys. In an ideal world the root-zone would be the anchor, and everything would flow from there.
Sadly, no. We also need to be able to deny the exitence of a record securely. Now, this is a real problem. The way DNS denies the existence of a record is to send an empty authoritative answer packet, which is smart as far as it goes, but it leaves us with a problem: there is nothing to sign.
HTTPS does not have this problem as it does secure transport, not secure message, so it can simply send a '404' response over its secure channel.
As noted the DNSSEC people are among the smartest in the world so they've figured out a solution: the 'Next Secure' NSEC record, known in its previous flawed incarnation as NXT.
Fundamentally it works like this: we have three records, called A, B and D. If a question comes in for C, we return the NSEC record that says that the 'Next Secure' record after B is D, which proves there is no C.
And because we CAN sign the NSEC record, this is secure. The NSEC record in the case above would look like this:
b.example.com. 86400 IN NSEC d.example.com. ( A RRSIG NSEC)
Note the 'A RRSIG NSEC'. This is where things get more complicated. This means that b.example.com has an A, RRSIG and an NSEC record.
Besides complete non-existence, there is also the case the record exists, but not the associated type. This happens for example when querying for an AAAA record for a host which has only an A record. Again, the normal DNS response is to send out an empty answer, which cannot be signed. In this case we again send out the NSEC record which lists which types DO exist, allowing the recipient to prove there is no AAAA record.
We previously noted that we can designate keys as 'anchors', once we have verified their authenticity using non-DNS means. It is impracticable to do this for all millions of domains though. So we need a way to have trusted keys (anchors) sign further keys, in hopes of one day having a signed root.
The proper place for such a signature is in the parent zone, of course, and for this purpose, DNSSEC has invented the Delegation Signer (DS) record. The size of the ccTLD zones is already worrisomely large, so the DS record only contains a hash of the signed zone.
The record looks like this:
dskey.example.com. 86400 IN DS 60485 5 1 ( 2BB183AF5F22588179A53B0A 98631FAD1A292118 )
This is the delegation signature, which would typically live in the .com zone, which corresponds
to this DNSKEY in the
example.com zone below:
dskey.example.com. 86400 IN DNSKEY 256 3 5 ( AQOeiiR0GOMYkDshWoSKz9Xz fwJr1AYtsmx3TGkJaNXVbfi/ 2pHm822aJ5iI9BMzNXxeYCmZ DRD99WYwYqUSdjMmmAphXdvx egXd/M5+X7OrzKBaMbCVdFLU Uh6DhweJBjEVv5f2wwjM9Xzc nOf+EPbtG9DMBmADjFDc2w/r ljwvFw== ) ; key id = 60485
Note how the key id was added as a comment here. Also note that the above makes no sense unless the DS record itself is signed with an RRSIG record with a key we do trust.
So if we have configured the .COM key as an anchor, we would also trust the DS record for
and henceforth also the signatures in the
example.com zone, and so forth.
It is all very pretty.
Sadly, no. Encryption keys sometimes needs to be changed (although unless you think your key got stolen, there is no need to do this in DNSSEC).
Using the scheme above, any change in key would have to be agreed with the registry (parent zone), which takes time to to process. Furthermore, the registry is probably not willing to change the key around a lot as they have better things to do.
So we invoke the magic incantation 'there is no problem in computing that cannot be solved by another layer of indirection', and add another layer of indirection.
This is called the 'Key Signing Key' (KSK), and that is the one that is 'blessed' by the parent zone. We then use the KSK to sign our Zone Signing Keys (ZKSs), which are used to sign our actual records. Note the plural, more about this later.
So the actual setup has, in addition to the DS and DNSKEY records shown above an additional layer in the form of another DNSKEY, which is signed with an RRSET based on the DNSKEY we already had. The key signed by our parent has the 'Secure Entry Point' flag set to designate it as the key to start with.
As stated above, there is a real need to change keys every once in a while, both regularly or in a hurry if they keys have been compromised.
During a change of keys, a situation might exist were caches still carry the old signatures, but resolvers can't find the associated keys to authenticate them with.
The solution for this is to make sure multiple keys and signatures are around, and only change one set at a time.
This needs to be done very carefully though, as any mistake will lead to 'bogus' data in DNSSEC parlance, which means that your records have signatures, but they can't be verified. Security-aware clients will now drop your data.
There are two proposed modes for ZSK rollover, which are detailed in DNSSEC Operational Practices by Olaf Kolkman: 'Pre-publish key set Rollover' and 'Double Signature Zone-signing Key Rollover', and yet more modes for KSK rollover.
Previously, DNSSEC took the labour-saving decision to not support wildcards. Wildcards in DNS synthesise records, which means that there is an infinite amount of signing to do in theory.
But then the DNSSEC people had a smart idea: make an RRSET state how many labels it covers. This means that 'www.example.com', synthesised by '*.example.com' is followed by a synthesised RRSET signing 'www.example.com'. However, this signature is then invalid, since it was signed as '*.example.com'. Now what?
Remember the unexplained number in the RRSET record? That is the amount of labels the RRSET covers, which would in this case be 2. The receiving nameserver can derive from this that the record 'www.example.com' was synthesised from '*.example.com', and check the signature accordingly.
This chapter has not been proofread and may very well be incorrect
This is sort of ironic. DNSSEC was meant to improve DNS Security, but over time it became clear it simultaneously lowered it in other ways.
Many DNS operators do not allow their zones to be transferred, as the full contents of a zone are considered private, and often provide hackers with clues on how to hack a network.
Recall how DNSSEC employs the NSEC record to securely deny existence of a zone, by signifying that no records exist between two records that do. So, the NSEC "covering" the domains 'a.ds9a.nl' and 'c.ds9a.nl' proves there is no 'b.ds9a.nl' record.
It turns out that if we start out from one NSEC record, we can find the next, and so on, therefore emulating a full zone transfer! By hopping from the "lower" part of the cover to the upper, we find a chain of NSEC records that lists the entire zone contents.
The upshot of this is that there is no longer the ability to restrict full access to a zone, as malicious users can simply hop all the NSEC records, and get the same thing.
This has meant that several large domain registries have stated that they cannot deploy DNSSEC in its present form, for example because of strict implementations of the EU privacy directive.
As stated before, the DNSSEC authors are pretty smart and know a lot about cryptography, so they've found a solution to this problem: NSEC3
In principle, this works just like regular NSEC, except that it operates on strong cryptographic hashes of domain names. By sending an NSEC3 response that covers the *hashes* that come before and after the hash of the record a query was sent for, the same proof of non-existence is available, without making it possible to enumerate the entire zone. One could enumerate the hashes, but as these are strong, they can't be converted back into domain names.
This is pretty smart, but also means the authoritative nameserver should keep the list of NSEC3 records in correct sorted order available. Things quickly get mighty complicated when wildcards are involved as well.
Additionally, the authoritative server has to do a lot more work, as it has to hash each question it can't immediately find an answer for to see which NSEC3 it should emit to prove non-existence.
Ok, if you've made it through the above, I suggest reading the DNSSEC HOWTO by Olaf Kolkman, which should now make sense.
The big worries to me are:
Huge answer records, making DNSSEC act as a packet-amplifier.
Complexity of key-rollover procedures. Automated key-rollover appears to be covered by patents.
Complexity of recursion process. Serving DNSSEC records is complex enough as it is, with NSEC taking the complexity-crown from the LOC record, but the recursing process is truly very hard.
The biggest worry: DNSSEC complexity is sure to cause secure unavailability of domain names, leading DNSSEC users to either turn it off or ignore its warnings.
Many of the worries above could be addressed with good toolsets and client library support, but the last and first factors will always remain. DNS often operates under the hood, many applications have no way to communicate with their end users.
For example, how would a MTA react to 'Bogus' data? Hold the email? Bounce it back to the original author asking for instructions? Send it anyhow? Policy is hard to set.
So I'm not sure yet if DNSSEC is worth it.