Monday, July 19, 2010

A signed root zone and an NSEC adventure

On 15-July-2010, the root zone of the Domain Name System was DNSSEC-enabled. The details of this effort, which was underway for some time, are outlined at http://www.root-dnssec.org. The signing of the root is regarded as an important step towards a broader DNSSEC deployment across the internet.



A good number of Top Level Domains (TLD) are already DNSSEC-enabled including .org, .gov and a several country code TLDs. Some more significant ones like .edu, .net and .com, the largest of them all, are scheduled to join in over the coming months. Information on DNSSEC deployment is available at http://www.dnssec-deployment.org.

A signed root allows recursive nameservers to be configured with a single top-level trust anchor. In its absence, a large number of trust anchors have to be included and they must be updated upon expiration, rollover and any other relevant events on their target keys. A list of trust anchors for the TLDs is available from the IANA Interim Trust Anchor Repository. The signed root should allow this interim repository to be retired.

DNSSEC is a complex beast - just the basic standard spans 3 RFCs and there are innumerable others that cover specific aspects of it. The aim is to provide data origin authentication and data integrity assurance for zone data. These two guarantees are widely accepted to be a robust and practical solution for preventing Kaminsky style Cache Poisoning attacks. Many of the intricacies of DNSSEC can be attributed to its support for offline signing whereby the private keys do not need to be used by the resolution servers for responding to queries. In fact, in certain critical cases, such as for the root zone KSK (Key Signing Key) which is the ultimate trust anchor, the private key can be stored in a locked safe most of the time and in an offline network-disconnected state during well-publicized key ceremonies. Actually root zone key management is quite challenging due to the fact that the ZSKs (Zone Signing Key) and the KSKs are owned and managed by different entities.

An interesting feature of DNSSEC is the NSEC (and NSEC3) resource record which is the basis for an authenticated denial of existence. If a signed version of a generic does not exist status code were to be used to indicate non-existence, a malicious entity could replay it to claim falsely that existing domains etc. do not exist. The NSEC record approach solves this problem and even allows negative responses to be cached like regular zone data. NSEC records are inserted into the zone during the signing process and logically represent missing regions. For example, the current root zone has an NSEC record for . (root) which mentions the TLD ac. as the next domain in canonical order.

. 86400 IN NSEC ac. NS SOA RRSIG NSEC DNSKEY
. 86400 IN RRSIG NSEC 8 0 86400 20100725070000 20100718060000 41248 . n0NneSwnSuez+CB6wbfcTmF38C5RF0329MXZIfXzn7mpqz/lB4Gm5n2Q UUwYENUJ9xh1P1JvGNLx1ES/11mcPdMzc2q8Y0TQ5/DieuwUkr+OLlx6 IMYx21nKw1vdToiwkEu00ZwVSM7rx/tItKYFRnZbW22IMziUuFSuUcUs o9U=

The following queries will return this NSEC record (and its signature) in the authority section of the response :-
  1. dig +dnssec @a.root-servers.net ab. ns
  2. dig +dnssec @a.root-servers.net . txt

The first query is for the TLD ab. which does not exist. The server returns a status code of NXDOMAIN and the NSEC record for . that points to the next domain ac. which is beyond ab. in canonical order. The second query is for a non-existent TXT RRset in . and the NSEC again indicates that ac. is the next domain after . which has NS, SOA, RRSIG, NSEC and DNSKEY records. The status code is NOERROR. Hence, in both cases, the NSEC record a signed response indicating non-existence of the queried RRset.

As you may have noticed or are already aware, NSEC records are a handy way of discovering all the delegated domains in a zone. A signed zone includes a closed NSEC chain where the NSEC record of the last domain points back to the apex domain. You could simply query the NSEC for ., discover that the next in canonical order is ac., query the NSEC for ac. and so on until you get an NSEC record whose next domain is . itself. This traversal is something that a lot of zone administrators want to avoid due to privacy concerns (and also the $$ for valuable domain name data). The NSEC3 standard, which is already used in several DNSSEC-enabled zones other than the root zone, is designed to prevent this type of zone walking.

But NSEC zone walking is not all that direct as we will soon find out. Let us see what happens if we try to traverse the root zone by dig-ing the A-root nameserver. In order to avoid missing the forest for the trees, we omit the +dnssec flag and get shorter unsigned responses.

dig @a.root-servers.net . nsec
=> . 86400 IN NSEC ac. NS SOA RRSIG NSEC DNSKEY
dig @a.root-servers.net ac. nsec
=> ac. 86400 IN NSEC ad. NS RRSIG NSEC
dig @a.root-servers.net ad. nsec
=> ad. 86400 IN NSEC ae. NS RRSIG NSEC
dig @a.root-servers.net ae. nsec
=> ae. 86400 IN NSEC aero. NS RRSIG NSEC
dig @a.root-servers.net aero. nsec
=> aero. 86400 IN NSEC af. NS RRSIG NSEC
...


It goes on smoothly like this until something interesting happens when arpa. is reached.

dig @a.root-servers.net arpa. nsec
=> arpa. 86400 IN NSEC e164.arpa. NS SOA RRSIG NSEC DNSKEY
The observant reader will notice that we have a 2nd level domain e164.arpa as the next domain which is not something we had encountered so far.
dig @a.root-servers.net e164.arpa. nsec
=> e164.arpa. 86400 IN NSEC in-addr.arpa. NS RRSIG NSEC
Again we see a 2nd level domain in-addr.arpa.
dig @a.root-servers.net in-addr.arpa. nsec
=> Something strange occurs as shown in the more detailed response below...

;; ->>HEADER<<- 62865="" id:="" noerror="" opcode:="" query="" span="" status:="">
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;in-addr.arpa. IN NSEC

;; AUTHORITY SECTION:
in-addr.arpa. 10800 IN SOA A.ROOT-SERVERS.NET. dns-ops.ARIN.NET. 2010071904 1800 900 691200 10800

Looks like we have been thrown off-track during our walk. Before we attempt to get to the bottom of what exactly has happened, let us try something...

dig +dnssec @a.root-servers.net arpa0. nsec

;; ->>HEADER<<- 8099="" id:="" nxdomain="" opcode:="" query="" span="" status:="">
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;arpa1. IN NSEC

;; AUTHORITY SECTION:
. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2010071801 1800 900 604800 86400
. 86400 IN RRSIG SOA 8 0 86400 20100725070000 20100718060000 41248 . bnVtybBY5V9Gaz5+7e+4+Ur44bqbqDvg1WwBkeFdeAtfmTUJdurpMFsc sjGpUh6LM0AWet7fxB+cTjVXPRGDGlsk84eDUSP1yYyiQJ3HDJSurAb+ G/N0HY7API6MPhoYrXe+fIcjzn0vAedxNgtdS4trTtSlQTUYNfp2+msm DyI=
. 86400 IN NSEC ac. NS SOA RRSIG NSEC DNSKEY
. 86400 IN RRSIG NSEC 8 0 86400 20100725070000 20100718060000 41248 . n0NneSwnSuez+CB6wbfcTmF38C5RF0329MXZIfXzn7mpqz/lB4Gm5n2Q UUwYENUJ9xh1P1JvGNLx1ES/11mcPdMzc2q8Y0TQ5/DieuwUkr+OLlx6 IMYx21nKw1vdToiwkEu00ZwVSM7rx/tItKYFRnZbW22IMziUuFSuUcUs o9U=
arpa. 86400 IN NSEC as. NS RRSIG NSEC
arpa. 86400 IN RRSIG NSEC 8 1 86400 20100725070000 20100718060000 41248 . s8dG/xy2i/iWGBTZrz01KByNsjD6MnBYEeXNndGA2k497x1mB7S9bfu5 eu6tiSqPAN02NHhB2gCbEWASaDfd/UtPDjrGxAmaeuxSmOX6DiImpGNm PDAoyCiRaxsDJuq2ugpsb5ef+YtKBGQ3wNoUv6AbPaxoi0Pu5sKlkBjH TK0=

In the authority section, we find an NSEC for arpa. that points to as. and we use that to continue our walk.

dig @a.root-servers.net as. nsec
=> as. 86400 IN NSEC asia. NS RRSIG NSEC
dig @a.root-servers.net asia. nsec
=> asia. 86400 IN NSEC at. NS RRSIG NSEC
dig @a.root-servers.net at. nsec
=> at. 86400 IN NSEC au. NS RRSIG NSEC

We seem to be good once again and just one step away from the land down under. So what went on since we queried the NSEC for arpa. ?

The first thing to note is that when we queried for the non-existent arpa0., the logical successor of arpa. in the canonical order, we got an NSEC for as. which does seem to be the next domain after arpa. in the root zone. However, the NSEC for arpa. did not point to as. but rather to e164.arpa which is a child of arpa.

Finally, the bulb lights up. The arpa zone also has an NSEC record for its apex arpa. and this is what we got ! Not the NSEC record for arpa. in the root zone. This is why it points to e164.arpa. which is in the arpa. zone and not in the root zone. And this means that although the arpa. zone is delegated by the root zone, the former is hosted by the root nameservers. This is not surprising considering the special status of arpa. . We can confirm this using dig @a.root-servers.net arpa. ns which returns the root nameservers A through M but excluding J.

So now we query j.root-servers.net for the NSEC of arpa. and we indeed get back an NSEC record that points to as.
=> arpa. 86400 IN NSEC as. NS RRSIG NSEC

This indeed confirms our diagnosis although I don't really know what is different about the J root that it does not host arpa.

We still have another item that needs to be pieced together to solve the puzzle. What happened when we queried the NSEC for in-addr.arpa. ?

We did not get back any answer section, we got a SOA record in the authority section and the status code was NOERROR. This makes it a NODATA response and that would imply that no NSEC record was found for in-addr.arpa. On the other hand, we did get back an NSEC for e164.arpa. that pointed to in-addr.arpa.

This too can be explained in exactly the same way - in-addr.arpa. is delegated but hosted on the same nameservers as arpa. while e146.arpa. is not. Additionally, in-addr.arpa. is not signed which leads to a NODATA response from its zone. This can be confirmed using the following queries :-

dig @a.root-servers.net e164.arpa. ns - returns nameservers that are distinct from the arpa. nameservers
dig @a.root-servers.net in-addr.arpa. ns - returns nameservers that are same as the arpa. nameservers
dig +dnssec @a.root-servers.net in-addr0.arpa. ns - no answer section but shows NSEC for in-addr-servers.arpa in the authority section

So we took quite a deep look at the chasms that can trap you while traversing the NSEC chain - it is clearly not all that trivial in practice. Most zones use NSEC3 which among other things makes traversal virtually impossible through the use of 1-way hashes instead of textual names for the next domain.

No comments:

Post a Comment