DNSSEC HOWTO, a tutorial in disguise
Olaf Kolkman
Revision 134
July 4,
2009
____________________________________________________________________
About This Document
This HOWTO is not a HOWTO.
In 2000-2001 this document started ts life as an addendum to a DNSSEC course I
organized at the RIPE NCC but in cause of time it has grown beyond the size of your
typical HOWTO and became a (hopefully) comprehensive tutorial on the subject of
DNSSEC and DNSSEC deployment.
This HOWTO is intended for those people who want to deploy DNSSEC and
are seeking a document that lives between a typical high level description
of the topic (see the excellent Surfnet White Paper on DNSSEC for that
(http://www.surfnet.nl/Documents/DNSSSEC-web.pdf ), the typical out of the box
recipe, and an in depth description of the technology.
I this tutorial we touch upon the following topics:
-
- Part I, intends to provide some background for those who want to deploy
DNSSEC.
-
- Part II, about the aspects of DNSSEC that deal with data security.
-
- Part III, describes a few tools that may turn out handy while figuring out what
might have gone wrong.
The documentation is based on the so called DNSSEC-bis specifications that where
finalised by the IETF DNSEXT working group in July 2004 and published in March
2005 as [3, 5, 4].
As of June 2009 the author is aware of the following open-source and or freeware
implementations of the DNSSEC-bis specifications: BIND, Unbound and NSD. All our
examples are based on BIND 9.6.1 and Unbound 1.3.0.
This document is not intended as an introduction to DNS. Basic knowledge of
DNS and acronyms used is assumed. We have tried not to use jargon but when
unavoidable we have tried to explain the meaning. If you want to know more about
the topic of DNS in general then Paul Albitz and Cricket Lui’s[2] or Ron Aitchinson’s
[1] text books provide an excellent introduction.
This document will be subject to change. Please regularly check
http://www.nlnetlabs.nl/dnssec_howto/dnssec_howto.pdf for new versions.
Your corrections and additions are appreciated.
Contents
Part I
DNSSEC, the background
1 A motivation for DNSSEC
The Domain Name System (DNS) is one of these essential elements that allowed the
Internet to evolve in what it is today.
It is used in almost every interaction that uses names in identifiers: Email, Web,
SIP based Voice over IP, Web services, Spam filtering, Internet messaging, and
many more. Yet, the DNS system was not designed with security in mind;
over 3 decades ago the environment it was developed for (and in) just looked
different. Regardless, given that the DNS is the largest distributed look-up
system on the Internet, one could claim that the protocol designers were
successful.
The fact that essential components in the DNS architecture, so called caching
nameservers, are subject to types of attacks that allow the inception of false data has
been known for almost 2 decades now.
As a result of such so called cache poisoning attacks, e-mails can be redirected and
copied before they are delivered to their final destination, voice over IP calls can be
tapped by third parties, and – given the circular dependency of the registration
process on the DNS – SSL certificates may not be as protective as one would
hope.
The DNS has become a utility that people depend on when moving about on the
Internet. It is a core part of the Internet Infrastructure and trust in the DNS is
necessary, albeit not sufficient, for trust in the Internet.
DNSSEC was designed to deal with cache poisoning and a set of other DNS
vulnerabilities such as man in the middle attacks and data modification in
authoritative servers. Its major objective is to provide the ability to validate the
authenticity and integrity of DNS messages in such a way that tampering with the
DNS information anywhere in the DNS system can be detected. This is the kind of
protection the DNS desperately needs.
Unfortunately, because of the distributed nature of the DNS, DNSSEC needs to be
deployed by a significant amount of DNS data providers before its utility becomes
relevant. Custodians of the DNS infrastructure such as TLDs and the root system
should provide a breeding ground on which DNSSEC can take off while ISPs and
enterprise DNS administrators prepare their DNS infrastructure to validate signed
data.
Obviously this is not going to be a project with immediate return on investment, it
is a long term strategy to allow us to put similar trust in the Internet as we did 10
years ago.
By introducing DNSSEC in your environment you do not only protect yourself or
the users of your data. But you also help in building a globally secure system that can
be used to bootstrap trust relations in other protocols.
Part II
Securing DNS data
This part deals with securing data in zone files. We describe how to
generate and manage keys, how to set up a recursive name server to
validate signed zone data and how to sign and serve zones.
2 Configuring a recursive name server to validate answers
2.1 Introduction
We plan to configure a recursive name server to validate the data it receives.
Users that use this recursive name server as their resolver will, then, only
receive data that is either secure and validated or not secured in any way.
As a result, secured data that fails validation will not find its way to the
users .
Having a validating recursive name server protects all those that use it as a forwarder
against receiving spoofed DNS data.
Figure 1 illustrates how to configure the recursive DNS servers with a
trusted key for ”example.com” so that all the data served by the authoritative
servers for ”example.com” is validated before it is handed to the protected
infrastructure that have the recursive servers configured as their forwarder
(the name servers that usually are assigned through DHCP or configured in
/etc/resolv.conf).
By configuring a public key for a specific zone, we tell the caching forwarder that
all data coming from that zone should be signed with the corresponding private key.
The zone acts as a secure entry point into the DNS tree and the key configured in the
recursive name server acts as the start for a chain of trust. In an ideal situation you
have only one key configured as a secure entry point: the key of the root
zone.
We assume you have configured your BIND nameserver to be recursive only or that
you use UNBOUND, which is recursive only.
We also assume that that name server in your organisation has been configured to
run as an authoritative server for a secured zone called example.net. Notes on how to
set up a secured zone can be found below in Chapter 3, ”Securing a DNS
zone”
2.2 Warning
Your recursive name server will treat the zones for which you configured trust anchors
as being secured. If the zones for which you have configured trust anchors change their
keys you will also have to reconfigure your trust anchors. Failure to do so will result in
the data in these zones, or any child, being marked as bogus and therefore becoming
invisible to users.
2.3 Configuring the caching forwarder
See AppendixB for information on compiling BIND with the correct switches
to allow for DNSSEC. Do not forget enter the dnssec-enable yes; and
dnssec-validation yes; statements in the options directive of your
named.conf.
As an alternative to bind you could use UNBOUND as a DNSSEC aware
recursive nameserver. UNBOUND does not need any special configuration
options except for the configuration of a trust-anchor to perform DNSSEC
validation.
2.3.1 Configuring a trust anchor
A trust anchor is a public key that is configured as the entry point for a chain of
authority. In the ideal case —where the root is signed and chains of trusts
can be constructed through top-level domains to end-nodes — validating
name servers would only need one of these trust anchors to be configured.
During early deployment you will probably want to configure multiple trust
anchors.
In Figure 2 we show a zone tree. In this tree, the domains nlnetlabs.nl,
194.in-addr.arpa, 193.in-addr.arpa and 0.0.193.in-addr.arpa are assumed to be
signed. It is also assumed that there is a secure delegation between 193.in-addr.arpa
and 0.0.193.in-addr.arpa. In order to validate all these domains, the validating DNS
client would have to configure trust anchors for nlnetlabs.nl, 194.in-addr.arpa and
193.in-addr.arpa.
2.3.2 How and where to get these trust anchors?
To configure a trust-anchor you have to obtain the public key of the zone that you
want to use as the start of the chain of authority that is to be followed when the data
is validated. It is possible to get these straight from from the DNS, but there are two
reasons why this may not be advisable.
Firstly, you have to establish the authenticity of the key you are about to configure
as your trust anchor. How you do this depends on on what method the zone owner has
made available for out of band validation of the key.
- You could do this by visiting the zone owners secure website and
validate the key information. For instance, the RIPE NCC signs a
number of reverse zones. They publish their public keys on through
<https://www.ripe.net/projects/disi/keys/>
- You could give the zone owner a call if you personally know them.
- You could trust the key that is published on the bill you just received from
the zone owner.
- You could just believe that your OS vendor did the validation on your
behalf.
Secondly, you may have a choice of public keys, in which case you need to select
the the proper ”Secure Entry Point” key.
In DNSSEC a difference is made between key- and zone-signing keys. Key-signing keys
exclusively sign the DNSKEY RR set at the apex, while zone-signing keys sign all RR sets in
a zone. .
Key-signing keys are often used as Secure Entry Points (SEP) keys. These SEP keys
are the keys intended to be first used when building a chain of authority from a
trust anchor to signed data. We advise a one-to-one mapping between SEP
keys and key-signing keys. In practise key-signing keys have a lower rollover
frequency than zone-signing keys so you should configure the SEP i.e. key-signing
keys.
In addition to having the proper public key you should either be aware of the
rollover policy of the zone owner, or that you have a tool that takes care of automated
rollover. Failure to modify the trust anchor before the corresponding SEP key is rolled
will result in validation failures.
Assume you have obtained the key-signing keys of nlnetlabs.nl.,
193.in-addr.arpa., and 195.in-addr.arpa.. To configure those key as a trust
anchor you will have tell your recursive nameserver to use those. For both BIND and
UNBOUND you can follow the following procedure.
Create a separate file that contains the keys in a trusted-keys directive as shown
in figure 3. The format is similar to the DNSKEY RR except that the ”DNSKEY”
label, the CLASS and the TTL, are omitted and quotes are placed around the name
and the public key material.
You can use the include statements in both UNBOUND and BIND to read the files
with the trusted keys directive into your configuration files.
2.3.3 Public repositories of trust-anchors
There are a few places where you can obtain trust-anchors.
-
The IANA ITAR
- (at https//itar.iana.org) is IANA’s Interim Trust
Anchor Repository to share the key material required to perform DNSSEC
verification of signed top-level domains, in lieu of a signed DNS root zone.
The tar publishes key information of TLDs, the exchange of information
between IANA and the TLDs is the same as would normally take place for
root-zone maintenance.
-
The UCLA secspider
- (at https://secspider.cs.ucla.edu) contains zones
that have
been submitted by users (via the on-line submission form), crawled from a
large list of over 2.5 million zones, and walked (via NSEC walking). Their
collection of keys in a format that is understood by Unbound and BIND is
available at: http://secspider.cs.ucla.edu/trust-anchors.conf.
-
The IKS Jena TAR
-
(at https://www.iks-jena.de/leistungen/dnssec.php is build from
scanning the DNS and by open registration, it is made available through
DLV.
2.3.4 Testing
As soon as a trusted-key has been configured, data from that zone or its sub zones
will be validated by the caching forwarder. You can test this by querying your
server . If
data is validated by the caching forwarder the ad-bit will be set by the name server
(see the ’flags’ in the following example).
; <<>> DiG 9.5.0-P2 <<>> @192.168.2.204 example.net SOA +dnssec +multiline +retry=1
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1397
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 3
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;example.net. IN SOA
;; ANSWER SECTION:
example.net. 100 IN SOA ns.example.net. olaf.nlnetlabs.nl. (
2002050501 ; serial
100 ; refresh (1 minute 40 seconds)
200 ; retry (3 minutes 20 seconds)
604800 ; expire (1 week)
100 ; minimum (1 minute 40 seconds)
)
example.net. 100 IN RRSIG SOA 5 2 100 20090803071330 (
20090704071330 17000 example.net.
TVgWsNQvsFmeNHAeccGi7+UI7KwcE9TXPuSvmV9yyJwo
4FvHkxVC1H+98EtrmbR4c/XcdUzdfgn+q+lBqNsnbAit
xFERwPxzxbX0+yeCdHbBjHe7OuOc2Gc+CH6SbT2lKwVi
iEx3ySqqNoVScoUyhRdnPV2A1LV0yd9GtG9mI4w= )
;; AUTHORITY SECTION:
example.net. 100 IN NS ns.example.net.
example.net. 100 IN RRSIG NS 5 2 100 20090803071330 (
20090704071330 17000 example.net.
Xuw7saDDi6+5Z7SmtC7FC2npPOiE8F9qMR87eA0egG0I
B+xFx7pIogoVIDpOd1h3jqYivhblpCoDSBQb2oMbVy3B
SX5cF0r7Iu/xKP8XrV4DjNiugpa+NnhEIaRqG5uoPFbX
4cYT51yNq70I5mJvvajJu7UjmdHl26ZlnK33xps= )
;; ADDITIONAL SECTION:
ns.example.net. 100 IN A 192.168.2.203
ns.example.net. 100 IN RRSIG A 5 3 100 20090803071330 (
20090704071330 17000 example.net.
YUj6wUw2hHpONnfN/rSJJaGve2NfA1TcROJV7FdKmXrk
Vn+gMp2pATijqKxG6nLMI/MnAs1bURYMMuBy6458y97v
0687s5ba2kaUwFgmV4UOn/TnAjwNBgSTkSK/TTGQVK3V
xw9uefiQprxG70Z1h6gLysWRgBc33JiQRvvn5nY= )
;; Query time: 5 msec
;; SERVER: 192.168.2.204#53(192.168.2.204)
;; WHEN: Sat Jul 4 10:13:34 2009
;; MSG SIZE rcvd: 639
It is important that you check that the validation is working correctly. This can be
done by using the BIND log facilities on the machine that is configured as the
validating recursive name server.
In BIND messages of a certain category can be logged to separate channels. The
channels determine where the messages go and to what severity level they will need to
be reported. The relevant category for DNSSEC validation is dnssec. In the example
below the errors of the dnssec category are directed to the dnssec_log channel. In
order to follow the validation process the channel has to log at least severity debug
3.
logging {
channel dnssec_log { // a DNSSEC log channel
file "log/dnssec" size 20m;
print-time yes; // timestamp the entries
print-category yes; // add category name to entries
print-severity yes; // add severity level to entries
severity debug 3; // print debug message <= 3 t
};
category dnssec { dnssec_log; };
}
The output in the log file will look similar to the output below. The attempt for
positive response validation shows how the validator tries to prove that the RR set is
trusted by following the chain of trust to the appropriate secure entry point, your
trusted-key statement. Chains of trust (see figure 4) start by the validation of a
signature over a DNSKEY RRset, then these keys are used to validate the DS RRset
that point to DNSKEY RRs in a child zone – which validates the DNSKEY RRs in
the child zone –, or the DNSKEYs can be used to validate the data you have
queried for. The log reflects the activity of the validator following the chain of
trust.
validating @0x100823a00: example.net SOA: starting
validating @0x100823a00: example.net SOA: attempting positive response validation
validating @0x100824800: example.net DNSKEY: starting
validating @0x100824800: example.net DNSKEY: attempting positive response validation
validating @0x100824800: example.net DNSKEY: verify rdataset (keyid=49656): success
validating @0x100824800: example.net DNSKEY: signed by trusted key; marking as secure
validator @0x100824800: dns_validator_destroy
validating @0x100823a00: example.net SOA: in fetch_callback_validator
validating @0x100823a00: example.net SOA: keyset with trust 7
validating @0x100823a00: example.net SOA: resuming validate
validating @0x100823a00: example.net SOA: verify rdataset (keyid=17000): success
validating @0x100823a00: example.net SOA: marking as secure
validator @0x100823a00: dns_validator_destroy
2.4 Finding trust-anchors
It is not trivial to find and maintain trust anchors. If you want to get started
with validation of DNSSEC here are a few places where you can find more
information.
2.5 Maintaining Trust Anchors
Once trust anchors are configured you will need to make sure they are kept in sync
with the key as published by the entity responsible for the zone to which it
belongs.
Keeping in sync with trust anchors is incredibly important and while
there is a standard to signal rollovers([16]) it is not yet widely deployed. Once
a maintainer of a zone uses the RFC5011 mechanisms there are a number
of tools to take care of the rollover, e.g. the NLnet Labs autotrust tool at
http://www.nlnetlabs.nl/projects/autotrust/’.
More attention to the maintenance of trust anchors will be paid in a future version
of this HOWTO.
2.6 Lookaside Validation
Remember figure 2. If you would like to validate all these islands you will have to
configure many trust-anchors, as in the example in figure 3.
In order to deal with this problem in absence of secure delegation from a small set
of trust-anchors (ideally only 1, the root), BIND supports, as of version 9.3.2, a
mechanism called lookaside validation [19, 18].
In the lookaside validation a DLV registry will maintain all the trust-anchors
you trust them to do the ”Good Thing”. The maintainers of zones that are
secure register their trust-anchors with the DLV registry and (non-standard
extensions) in BIND (as of 9.3.2) will allow you, operator of a validating
nameserver, to make use of all trust anchors that are present in the DLV
tree.
In the DLV scheme the trust anchors are published in a dedicated domain
(dlv.isc.org in the figure 5). Whenever a validating resolver recognises
that a zone is signed it will first try to validate it by assessing if it is within
the island of trust configured by its local trust anchors. When the validated
domain is not in a trusted island the resolver will lookup perform a lookup
in the DLV domain and use the trust anchor from that zone if and when
available.
2.6.1 Configuring lookaside validation
What follows is a generic description if you want to configure ISC’s DLV as your
authoritative lookaside domain you may want to read http://www.isc.org/ops/dlv/.
In the example below we assume that dlv-registry.org is the registry of our
choice.
You have to perform two (additional) steps in order to turn on lookaside
validation.
Configure a trust anchor for the DLV registry.
You do this by defining a trust anchor for the island of trust defined by
dlv-registry.org in named.conf. Obviously, this trust-anchor is not exclusive, any
trust-anchor configured in your trusted-keys statement will have preference over the
data in the DLV registry.
trusted-keys {
//
// this trust-anchor defines dlv-registry.org as a trusted island.
//
"dlv-registry.org." 257 3 5
"AQPXP7B3JTdPPhMl ... u82ggY2BKPQ==";
//
// Other trust anchors below.
//
"nlnetlabs.nl." 3 5
"AQPzzTWMz8qSWI ... zMG1UBYtEIQ==";
"193.in-addr.arpa." 257 3 5
"AwEAAc2RnCT1gj ... pWaM8qXXPN8E=";
"195.in-addr.arpa." 257 3 5
"AwEAAaMN4kOrGai ... DjegV39vTJQ2c=";
};
Configuring how the DNS name space anchors in the DLV name space.
By using the dnssec-lookaside statement in the options section of
named.conf. The statement takes two arguments the first one is the domain in the
DNS for which lookaside validation is to be applied. Usually this will be the
full name space so the "." (root) is configured. The second argument is the
name of the trust-anchor where a lookup should be performed for a DLV
record.
It is best to configure only one DLV trust-anchor.
options {
// DNSSEC should be turned on, do not forget
dnssec-enable yes;
dnssec-validation yes;
// This sets the dlv registry "dlv-registry.org"
dnssec-lookaside "." trust-anchor "dlv-registry.org.";
// other options are skipped in this example
};
testing
When you have your logging configured as described in section 2.3.4 i.e. you log
errors of the dnssec category are directed to a channel that logs at least at severity
debug 3, then your log output when querying for example.net SOA will be similar to
what is shown below.
First, the amount of log-ouput to validate one query covers more than one
page of fine print. On a production server this data for several validation
sequences will be print mixed. It will be very hard to debug from logfiles on
production servers if you have not first looked at what happens for a single
query.
Second, the structure is that the validator first finds DNSSEC RRs, notices that
those records are not secure according ’plain DNSSEC’ and then moves to DLV
validation.
Third, small chains of trust are build, from the DLV trust-anchor, via
DNSKEY RRs to the signatures over the data. Try to follow these trust anchors
in the example output so it will be easier to identify them in production
logs.
validating @0x100824800: . NS: starting
validating @0x100824800: . NS: looking for DLV
validating @0x100824800: . NS: plain DNSSEC returns unsecure (.): looking for DLV
validating @0x100824800: . NS: looking for DLV dlv-registry.org
validating @0x100824800: . NS: DLV lookup: wait
validating @0x100823a00: example.net SOA: starting
validating @0x100823a00: example.net SOA: looking for DLV
validating @0x100823a00: example.net SOA: plain DNSSEC returns unsecure (.): looking for DLV
validating @0x100823a00: example.net SOA: looking for DLV example.net.dlv-registry.org
validating @0x100823a00: example.net SOA: DNS_R_COVERINGNSEC
validating @0x100823a00: example.net SOA: covering nsec: trust 1
validating @0x100823a00: example.net SOA: DLV lookup: wait
validating @0x1008dda00: dlv-registry.org DLV: starting
validating @0x1008dda00: dlv-registry.org DLV: attempting negative response validation
validating @0x1008de800: dlv-registry.org SOA: starting
validating @0x1008de800: dlv-registry.org SOA: attempting positive response validation
validating @0x1008df600: example.net.dlv-registry.org DLV: starting
validating @0x1008df600: example.net.dlv-registry.org DLV: attempting positive response validation
validating @0x1008e0400: dlv-registry.org DNSKEY: starting
validating @0x1008e0400: dlv-registry.org DNSKEY: attempting positive response validation
validating @0x1008e0400: dlv-registry.org DNSKEY: verify rdataset (keyid=8916): success
validating @0x1008e0400: dlv-registry.org DNSKEY: signed by trusted key; marking as secure
validator @0x1008e0400: dns_validator_destroy
validating @0x1008de800: dlv-registry.org SOA: in fetch_callback_validator
validating @0x1008de800: dlv-registry.org SOA: keyset with trust 7
validating @0x1008de800: dlv-registry.org SOA: resuming validate
validating @0x1008de800: dlv-registry.org SOA: verify rdataset (keyid=27467): success
validating @0x1008de800: dlv-registry.org SOA: marking as secure
validator @0x1008de800: dns_validator_destroy
validating @0x1008dda00: dlv-registry.org DLV: in authvalidated
validating @0x1008dda00: dlv-registry.org DLV: resuming nsecvalidate
validating @0x1008df600: example.net.dlv-registry.org DLV: in fetch_callback_validator
validating @0x1008df600: example.net.dlv-registry.org DLV: keyset with trust 7
validating @0x1008df600: example.net.dlv-registry.org DLV: resuming validate
validating @0x1008df600: example.net.dlv-registry.org DLV: verify rdataset (keyid=27467): success
validating @0x1008df600: example.net.dlv-registry.org DLV: marking as secure
validator @0x1008df600: dns_validator_destroy
validating @0x100823a00: example.net SOA: in dlvfetched: success
validating @0x100823a00: example.net SOA: DLV example.net found
validating @0x100823a00: example.net SOA: dlv_validator_start
validating @0x100823a00: example.net SOA: restarting using DLV
validating @0x100823a00: example.net SOA: attempting positive response validation
validating @0x1008de800: dlv-registry.org NSEC: starting
validating @0x1008de800: dlv-registry.org NSEC: attempting positive response validation
validating @0x1008de800: dlv-registry.org NSEC: keyset with trust 7
validating @0x1008de800: dlv-registry.org NSEC: verify rdataset (keyid=27467): success
validating @0x1008de800: dlv-registry.org NSEC: marking as secure
validator @0x1008de800: dns_validator_destroy
validating @0x1008dda00: dlv-registry.org DLV: in authvalidated
validating @0x1008dda00: dlv-registry.org DLV: looking for relevant nsec
validating @0x1008dda00: dlv-registry.org DLV: nsec proves name exists (owner) data=0
validating @0x1008dda00: dlv-registry.org DLV: resuming nsecvalidate
validating @0x1008dda00: dlv-registry.org DLV: nonexistence proof(s) found
validator @0x1008dda00: dns_validator_destroy
validating @0x100824800: . NS: in dlvfetched: ncache nxrrset
validating @0x100824800: . NS: DLV not found
validating @0x100824800: . NS: marking as answer
validator @0x100824800: dns_validator_destroy
validating @0x100824800: example.net DNSKEY: starting
validating @0x100824800: example.net DNSKEY: looking for DLV
validating @0x100824800: example.net DNSKEY: plain DNSSEC returns unsecure (.): looking for DLV
validating @0x100824800: example.net DNSKEY: looking for DLV example.net.dlv-registry.org
validating @0x100824800: example.net DNSKEY: DLV example.net found
validating @0x100824800: example.net DNSKEY: dlv_validator_start
validating @0x100824800: example.net DNSKEY: restarting using DLV
validating @0x100824800: example.net DNSKEY: attempting positive response validation
validating @0x100824800: example.net DNSKEY: dlv_validatezonekey
validating @0x100824800: example.net DNSKEY: Found matching DLV record: checking for signature
validating @0x100824800: example.net DNSKEY: verify rdataset (keyid=17000): RRSIG failed to verify
validating @0x100824800: example.net DNSKEY: verify rdataset (keyid=49656): success
validating @0x100824800: example.net DNSKEY: marking as secure
validator @0x100824800: dns_validator_destroy
validating @0x100823a00: example.net SOA: in fetch_callback_validator
validating @0x100823a00: example.net SOA: keyset with trust 7
validating @0x100823a00: example.net SOA: resuming validate
validating @0x100823a00: example.net SOA: verify rdataset (keyid=17000): success
validating @0x100823a00: example.net SOA: marking as secure
validator @0x100823a00: dns_validator_destroy
When using lookaside validation assessing the log output in case of corrupted zone
data is a challenge. Below is the output of the validator when it tries to figure out if a
query that returns a corrupted result is valid or not. The conclusion is reached in the
last few lines.
validating @0x100824800: . NS: starting
validating @0x100824800: . NS: looking for DLV
validating @0x100824800: . NS: plain DNSSEC returns unsecure (.): looking for DLV
validating @0x100824800: . NS: looking for DLV dlv-registry.org
validating @0x100824800: . NS: DLV lookup: wait
validating @0x100823a00: corrupt.example.net A: starting
validating @0x100823a00: corrupt.example.net A: looking for DLV
validating @0x100823a00: corrupt.example.net A: plain DNSSEC returns unsecure (.): looking for DLV
validating @0x100823a00: corrupt.example.net A: looking for DLV corrupt.example.net.dlv-registry.org
validating @0x100823a00: corrupt.example.net A: DNS_R_COVERINGNSEC
validating @0x100823a00: corrupt.example.net A: covering nsec: trust 1
validating @0x100823a00: corrupt.example.net A: DLV lookup: wait
validating @0x1008dba00: dlv-registry.org DLV: starting
validating @0x1008dba00: dlv-registry.org DLV: attempting negative response validation
validating @0x1008dc800: dlv-registry.org SOA: starting
validating @0x1008dc800: dlv-registry.org SOA: attempting positive response validation
validating @0x1008dd600: corrupt.example.net.dlv-registry.org DLV: starting
validating @0x1008dd600: corrupt.example.net.dlv-registry.org DLV: attempting negative response validation
validating @0x1008de400: dlv-registry.org SOA: starting
validating @0x1008de400: dlv-registry.org SOA: attempting positive response validation
validating @0x1008df200: dlv-registry.org DNSKEY: starting
validating @0x1008df200: dlv-registry.org DNSKEY: attempting positive response validation
validating @0x1008df200: dlv-registry.org DNSKEY: verify rdataset (keyid=8916): success
validating @0x1008df200: dlv-registry.org DNSKEY: signed by trusted key; marking as secure
validator @0x1008df200: dns_validator_destroy
validating @0x1008dc800: dlv-registry.org SOA: in fetch_callback_validator
validating @0x1008dc800: dlv-registry.org SOA: keyset with trust 7
validating @0x1008dc800: dlv-registry.org SOA: resuming validate
validating @0x1008dc800: dlv-registry.org SOA: verify rdataset (keyid=27467): success
validating @0x1008dc800: dlv-registry.org SOA: marking as secure
validator @0x1008dc800: dns_validator_destroy
validating @0x1008dba00: dlv-registry.org DLV: in authvalidated
validating @0x1008dba00: dlv-registry.org DLV: resuming nsecvalidate
validating @0x1008de400: dlv-registry.org SOA: in fetch_callback_validator
validating @0x1008de400: dlv-registry.org SOA: keyset with trust 7
validating @0x1008de400: dlv-registry.org SOA: resuming validate
validating @0x1008de400: dlv-registry.org SOA: verify rdataset (keyid=27467): success
validating @0x1008de400: dlv-registry.org SOA: marking as secure
validator @0x1008de400: dns_validator_destroy
validating @0x1008dd600: corrupt.example.net.dlv-registry.org DLV: in authvalidated
validating @0x1008dd600: corrupt.example.net.dlv-registry.org DLV: resuming nsecvalidate
validating @0x1008de400: example.net.dlv-registry.org NSEC: starting
validating @0x1008de400: example.net.dlv-registry.org NSEC: attempting positive response validation
validating @0x1008de400: example.net.dlv-registry.org NSEC: keyset with trust 7
validating @0x1008de400: example.net.dlv-registry.org NSEC: verify rdataset (keyid=27467): success
validating @0x1008de400: example.net.dlv-registry.org NSEC: marking as secure
validator @0x1008de400: dns_validator_destroy
validating @0x1008dd600: corrupt.example.net.dlv-registry.org DLV: in authvalidated
validating @0x1008dd600: corrupt.example.net.dlv-registry.org DLV: looking for relevant nsec
validating @0x1008dd600: corrupt.example.net.dlv-registry.org DLV: nsec range ok
validating @0x1008dd600: corrupt.example.net.dlv-registry.org DLV: resuming nsecvalidate
validating @0x1008dd600: corrupt.example.net.dlv-registry.org DLV: in checkwildcard: *.example.net.dlv-registry.org
validating @0x1008dd600: corrupt.example.net.dlv-registry.org DLV: looking for relevant nsec
validating @0x1008dd600: corrupt.example.net.dlv-registry.org DLV: nsec range ok
validating @0x1008dd600: corrupt.example.net.dlv-registry.org DLV: nonexistence proof(s) found
validator @0x1008dd600: dns_validator_destroy
validating @0x100823a00: corrupt.example.net A: in dlvfetched: ncache nxdomain
validating @0x100823a00: corrupt.example.net A: looking for DLV example.net.dlv-registry.org
validating @0x100823a00: corrupt.example.net A: DLV lookup: wait
validating @0x1008dc800: dlv-registry.org NSEC: starting
validating @0x1008dc800: dlv-registry.org NSEC: attempting positive response validation
validating @0x1008dc800: dlv-registry.org NSEC: keyset with trust 7
validating @0x1008dc800: dlv-registry.org NSEC: verify rdataset (keyid=27467): success
validating @0x1008dc800: dlv-registry.org NSEC: marking as secure
validator @0x1008dc800: dns_validator_destroy
validating @0x1008dba00: dlv-registry.org DLV: in authvalidated
validating @0x1008dba00: dlv-registry.org DLV: looking for relevant nsec
validating @0x1008dba00: dlv-registry.org DLV: nsec proves name exists (owner) data=0
validating @0x1008dba00: dlv-registry.org DLV: resuming nsecvalidate
validating @0x1008dba00: dlv-registry.org DLV: nonexistence proof(s) found
validator @0x1008dba00: dns_validator_destroy
validating @0x100824800: . NS: in dlvfetched: ncache nxrrset
validating @0x100824800: . NS: DLV not found
validating @0x100824800: . NS: marking as answer
validator @0x100824800: dns_validator_destroy
validating @0x100824800: example.net.dlv-registry.org DLV: starting
validating @0x100824800: example.net.dlv-registry.org DLV: attempting positive response validation
validating @0x100824800: example.net.dlv-registry.org DLV: keyset with trust 7
validating @0x100824800: example.net.dlv-registry.org DLV: verify rdataset (keyid=27467): success
validating @0x100824800: example.net.dlv-registry.org DLV: marking as secure
validator @0x100824800: dns_validator_destroy
validating @0x100823a00: corrupt.example.net A: in dlvfetched: success
validating @0x100823a00: corrupt.example.net A: DLV example.net found
validating @0x100823a00: corrupt.example.net A: dlv_validator_start
validating @0x100823a00: corrupt.example.net A: restarting using DLV
validating @0x100823a00: corrupt.example.net A: attempting positive response validation
validating @0x100824800: example.net DNSKEY: starting
validating @0x100824800: example.net DNSKEY: looking for DLV
validating @0x100824800: example.net DNSKEY: plain DNSSEC returns unsecure (.): looking for DLV
validating @0x100824800: example.net DNSKEY: looking for DLV example.net.dlv-registry.org
validating @0x100824800: example.net DNSKEY: DLV example.net found
validating @0x100824800: example.net DNSKEY: dlv_validator_start
validating @0x100824800: example.net DNSKEY: restarting using DLV
validating @0x100824800: example.net DNSKEY: attempting positive response validation
validating @0x100824800: example.net DNSKEY: dlv_validatezonekey
validating @0x100824800: example.net DNSKEY: Found matching DLV record: checking for signature
validating @0x100824800: example.net DNSKEY: verify rdataset (keyid=17000): RRSIG failed to verify
validating @0x100824800: example.net DNSKEY: verify rdataset (keyid=49656): success
validating @0x100824800: example.net DNSKEY: marking as secure
validator @0x100824800: dns_validator_destroy
validating @0x100823a00: corrupt.example.net A: in fetch_callback_validator
validating @0x100823a00: corrupt.example.net A: keyset with trust 7
validating @0x100823a00: corrupt.example.net A: resuming validate
validating @0x100823a00: corrupt.example.net A: verify rdataset (keyid=17000): RRSIG failed to verify
validating @0x100823a00: corrupt.example.net A: failed to verify rdataset
validating @0x100823a00: corrupt.example.net A: verify failure: RRSIG failed to verify
validating @0x100823a00: corrupt.example.net A: no valid signature found
validator @0x100823a00: dns_validator_destroy
2.7 Some Troubleshooting Tips
Suppose that you have configured a trust anchor and you are experiencing problems.
For instance, your nameserver returns ”SERVFAIL” for particular queries. Well,
”SERVFAIL” is the default return code that a validating nameserver returns when it
flags data as being bogus. Bogus data can be caused by two things. Either you are
under attack or you experiencing a configuration error either by the operator of one of
the zones in the chain of trust or by the operator of the validating recursive
nameserver.
In addition to looking at the logs there are a number of tools at your disposal
(see III). To assess if problems occur because of misconfiguration, or bugs, in you
validating nameserver, or because of problems with the signed zones you will need a
troubleshooting strategy.
One of the approaches you could take is to first use drill (see 6) or dig (see 7) to
perform a ’sigchase’ or a ’trace’ with a key copied to your local file system,
circumventing you validating recursive nameserver. In that way you will be able to
check if the chain of trust can actually be built from the data. Make sure you use the
correct trust-anchor when tracing data.
When you have verified that the chain of trust can be build from the
data in the DNS it is time to troubleshoot the validating nameserver. This is
easy when you have access to the log files but may be more troublesome if
you don’t. You could use dig to query the validating nameservers with and
without the +cd flag. That flag sets a bit in the query that instructs the
nameserver not to perform validation. When the individual pieces in the
chain of trust (drill returned those when using the trace option) you may
be able to find inconsistencies that indicate that an expired trust anchor
has been configured. You start by querying the DNSKEY RRset for which
you assume there is a trust-anchor considered and work your way down. Or,
alternatively, you query for the data you were looking for, use the data in the
RRSIG RR to find for which DNSKEY RR to query, then query for a DS
RR at the same name and work your way up (similar to the ’sigchase’ in
drill).
While troubleshooting there are a number of failures that are easily introduced.
Take the following example.
In his ISP column [9, 8, 7], Geoff Huston documented his experiences as an early
deployer. He blindly configured a trust-anchor for the ”nlnetlabs.nl” zone. While this
zone was signed it was done in an experimental setup whereby not all servers for the
zone were configured with the same version of the protocol. In this case one of the
servers would not provide RRSIGs with the answer, something which may give rise to
re-occurring but hard to predict failures.
There are two things to learn from this: Never blindly configure trust anchors in
validating resolvers and make sure that when you serve zones all your servers conform
to the DNSSEC protocol specification.
Another failure is that one of the RRsets in the chain of trust has expired
signatures. Check this by looking at the date fields in the RRSIG RRs.
More problematic to find may be a rollover, where DNSKEY RRs or RRSIG RRs
have been removed to early so that there is an inconsistency between data in
cache and data that needs to be validated (also see section 5). Using the +cd
to with dig and looking at the TTLs might help to distinguish if you are
trying to validate RRSIGs for which there are no DNSKEYs available (or vice
verse).
3 Securing a DNS zone
3.1 Introduction
If a zone has been signed and its key has been configured in a validating
recursive name server we usually refer to it as being an ”island of security”.
It apparently does not have a secured parent and stands alone in the sea
of other unsecured domains. Usually creating an ”island of security” is the
first step to becoming part of the secure DNS. The ”island of security” will
remain ”insecure” for resolvers that have no trust anchor configured for the
domain.
If a zone owner decides to create ”an island of security” she will sign her zones and
distribute the ”secure entry points” to the system administrators that want to validate
her zone data. Once the island of security has been set up the island can
become part of the secure tree by exchanging the ”secure entry point” with the
parent.
After creation of the key-pairs used for signing and validation we want to sign the
zone data for our own organisation (e.g. example.net.) and configure the caching
forwarders on our organisations network to validate data against the public key of our
organisation.
In the text below, we assume that your organisation’s domain names are
maintained in one zone. If domain name administration is delegated to sub-zones,
see section Chapter 4, ”Delegating of signing authority; becoming globally
secure”.
Signing the zone data is the task of the zone administrator, configuring the caching
forwarder is a task of system administrators.
The examples are based on the example zone in section Figure 7.
3.2 Configuring authoritative servers
All the authoritative servers will need to be configured to deal with the DNSSEC
protocol. How this is done for BIND is explained in AppendixB. The essential steps
are compiling bind with openssl and enabling dnssec through the use of the
dnssec-enable yes; directive in the options section of named.conf.
That is all there is to it.
3.3 Creating key pairs
3.3.1 Key Maintenance Policy
Before generating keys, you will need to think about your key maintenance policy.
Such policy should address
- What will be the sizes of your keys?
- Will you separate the key- and zone-signing keys functionality?
- How often will you roll the keys?
- How will system administrators that intend to use your zone as a trust
anchor get hold of the appropriate public key and what mechanism will you
provide to enable them to validate the authenticity of your public key?
- How will you signal a key rollover or how can you make sure that all
interested parties are aware of a rollover?
Some of these issues may be easy to address. For example, your organisation may
have established mechanisms to distribute the public keys, there may be obvious
ways to publish an upcoming rollover such as the possibility of publishing the
event in a corporate newspaper. Alternatively, it may be possible to notify all
relevant parties by mail when a corporate X.509 hierarchy is available for e-mail
validation.
Key- and zone-signing keys.
The author thinks it is good practise to use zone-signing keys and key-signing keys
(also see Chapter 5, ”Rolling keys”). The key-signing keys are usually the first
keys from your zone that are used to build a chain of authority to the data
that needs to be validated. Therefore, these keys are often called a secure
entry point key (or SEP key). These SEP keys are the ones that you should
exchange with your parents or that validating resolvers configure as their trust
anchors.
Throughout this document we assume that you use separate key- and zone-signing
keys and that the key-signing keys are exclusively used as secure entry point keys
and can be identified by the SEP[11] bit in the flag field; the flag field is
odd.
3.3.2 Creating the keys
dnssec-keygen is the tool that we use to generate key pairs. The arguments that
we have to provide dnssec-keygen are shown in Figure 6.
The output can be found in two files. The name of the files contain relevant
information:
Kdomain_name+algorithm_id+key_id.extension
The domain_name is the name specified on the command line. It is used by other
BIND DNSSEC tools, if you use a different name from the domain name, you might
confuse those tools. The algorithm_id identifies the algorithm used: 1 for RSAMD5,
3 for DSA, 5 for RSASHA1 and 54 for HMAC-MD5 (TSIG only). The key_id is an
identifier for the key material. This key_id is used by the RRSIG Resource Record.
The extension is either key or private, the first is the public key, the second is the
private key.
We create an RSASHA1 zone-signing key pair for example.net:
# dnssec-keygen -r/dev/random -a RSASHA1 -b 1024 -n ZONE example.net
Kexample.net.+005+17000
Because of the considerations in Section 3.3.1 you will also need to create SEP
keys. Create keys with the SEP bit set by specifying the -f KSK flag with
dnssec-keygen.
# dnssec-keygen -r/dev/random -f KSK -a RSASHA1 -b 1280 -n ZONE example.net
Kexample.net.+005+49656
Lets have a look at the content of these
files
cat Kexample.net.+005+17000.key
example.net. IN DNSKEY 256 3 5 (
AQPI4+0M1V055RS2Hqv+8w8V20Dh+SQmFzHQtZMuzLH3UxWE0GmG5Gfj
ijandJeAZTKLpERXB6RfHTHGG8lD3IO1azWN6DiVFEVzgr0otAdDonfY
+oEsRw== )
The public key (.key extension) is exactly as it appears in your zone file. Note,
that the TTL value is not specified. This key has a ”flag” value of 256. Since this value
is an even number, the key is not marked as a SEP key and should be used for
zone-signing.
The private key (.private extension) contains all the parameters that make an
RSASHA1 private key. The private key of a RSA key contains different parameters to
DSA. Here is the private key (with base64 material truncated):
cat Kexample.net.+005+17000.private
Private-key-format: v1.2
Algorithm: 5 (RSASHA1)
Modulus: yOPtDNVdOeUUth6r/vMPFdtA4fkkJhcx0LWTLsyx91MVhNBphu...
PublicExponent: Aw==
PrivateExponent: he1Iszjo0UNjJBRyqfdfY+eAlqYYGWTL4HkMyd3L+j...
Prime1: +X0kNW1JrepBnVw5o9fDUyWAT5zqxKt0YR4vJZ19991tLZAmdO4...
Prime2: ziIX5qfpZGBuzfd847TqtDfYcwv5UfUrPAIa/11g3leUUNERmsB...
Exponent1: plNtePOGc/GBE5LRF+Us4hkANRNHLcei62l0w75T+pOeHmAZ...
Exponent2: iWwP7xqbmEBJ3qT97SNHIs/logf7i/jHfVa8qj5AlDpi4Ith...
Coefficient: rmmgD9P7/ywQJ4F0epdGqOUoQZmqrPQsraDTD8vkU1wLju...
This private key should be kept
secure
i.e. the file permissions should be set so that the zone administrator will be able
to access them when a zone needs to be signed. The BIND tools will, by
default,
look for the keys in the directory where signing is performed (see Section 3.4), that
might not be the most secure place on your OS.
3.4 Zone-signing
When you create key pairs, you should include them in your zone file. Refer to the
example in Figure7, where we use the $include directive to include the keys. We
increase the serial number in the SOA record before signing.
In the example below we will use the RSASHA1 type keys for zone and key-signing
keys.
Once the key is included in the zone file we are ready to sign the zone using the
dnssec-signzone tool (see Figure 8 for all the arguments). We use the -o flag to
specify the origin of the zone; by default the origin is deduced from the zone file
name.
With the ’-k key_name’ we specify which key is to be used as the key-signing key.
That key will only sign the DNSKEY RR set in the apex of the zone. The
keys that come as arguments at the end of the command are used to sign
all the RR data for which the zone is authoritative. If you do not specify
the keys, BIND will use the ones for which the public keys are included in
the zone and use the SEP flag to distinguish between key- and zone-signing
keys.
In practise you would not want to rely on the default, since in key rollover
scenarios you will have a public key in your zone file but you would not want to use
that for zone-signing (in order to avoid double signatures and therefore longer
signature generation times and more resource consumption on your name server).
Below is the command issued to sign a zone with the 49656 key as key-signing key and
the 17000 key as zone-signing key.
/usr/local/sbin/dnssec-signzone \
-o example.net \
-k Kexample.net.+005+49656 \
db.example.net \
Kexample.net.+005+17000.key
The signed zone file is reproduced in figure 3.4 . Note that the apex
DNSKEY RRset is the only RRset with two signatures, made with the zone- and
key-signing keys. The other RRsets are only signed with the zone-signing
keys.
The signing process completed the following:
- Sorted the zone in ’canonical’ order .
- Inserted NSEC records for every label.
- Added the key-id as a comment to each DNSKEY-record.
- Signed the DNSKEY RR set with two keys; the key-signing key and the
zone-signing key.
- Signed the other RRs with the zone-signing key.
- It created two files, dsset-example.net and keyset-example.net. These
two files are relevant when building a chain of trust. Per default the
files are created in the ’current directory’ i.e. the directory in which you
ran thednssec-signzone command, but when specifying the -d, with its
directory, then the files end up there.
The signatures were created with a default life time of 30 days from the moment of
signing. Once signatures have expired data can not be validated and your zone will
marked ’bogus’. Therefore you will have to re-sign your zone within 30 days. Zone
re-signing is discussed below.
The signed zone is stored in db.example.net.signed, make sure you have
configured named to use this file to serve the zones from.
; File written on Sat Jul 4 10:13:30 2009
; dnssec\_signzone version 9.5.0-P2
example.net. 100 IN SOA ns.example.net. olaf.nlnetlabs.nl. (
2002050501 ; serial
100 ; refresh (1 minute 40 seconds)
200 ; retry (3 minutes 20 seconds)
604800 ; expire (1 week)
100 ; minimum (1 minute 40 seconds)
)
100 RRSIG SOA 5 2 100 20090803071330 (
20090704071330 17000 example.net.
TVgWsNQvsFmeNHAeccGi7+UI7KwcE9TXPuSv
mV9yyJwo4FvHkxVC1H+98EtrmbR4c/XcdUzd
fgn+q+lBqNsnbAitxFERwPxzxbX0+yeCdHbB
jHe7OuOc2Gc+CH6SbT2lKwViiEx3ySqqNoVS
coUyhRdnPV2A1LV0yd9GtG9mI4w= )
100 NS ns.example.net.
100 RRSIG NS 5 2 100 20090803071330 (
20090704071330 17000 example.net.
Xuw7saDDi6+5Z7SmtC7FC2npPOiE8F9qMR87
eA0egG0IB+xFx7pIogoVIDpOd1h3jqYivhbl
pCoDSBQb2oMbVy3BSX5cF0r7Iu/xKP8XrV4D
jNiugpa+NnhEIaRqG5uoPFbX4cYT51yNq70I
5mJvvajJu7UjmdHl26ZlnK33xps= )
100 NSEC *.example.net. NS SOA RRSIG NSEC DNSKEY
100 RRSIG NSEC 5 2 100 20090803071330 (
20090704071330 17000 example.net.
aDLo8JH5jEqD9u3Ft+7CNF8YXM9LKLKcDsLv
otIcpixsMSXlXFSZOIkxkxZtwlqBwhz0nzIs
7M/tnvsTlf14I5nt/VPRBY/XxanOa/3GjXLo
5Ukig8gX4S7s6/iTHNIFjJaxHiCtt5zwoI/H
TeKi9FjuH9ysHVuoHeYR06MN/LU= )
100 DNSKEY 256 3 5 (
AQPI4+0M1V055RS2Hqv+8w8V20Dh+SQmFzHQ
tZMuzLH3UxWE0GmG5GfjijandJeAZTKLpERX
B6RfHTHGG8lD3IO1azWN6DiVFEVzgr0otAdD
onfYF8gUT03ZnRcXlkJk41h12NOfq6rkODaF
nfMHCppI3WZ/MJqe+9hLJtis+oEsRw==
) ; key id = 17000
100 DNSKEY 257 3 5 (
AQOzgs4qea+ImJ1OCworkabHqFnvPKybVT7b
nDIkJ2HvXWslbwNWJ66Ox3N6ftpCTc9wWBMw
5+xOh7ilTwFPruMa2gURwEywZaMG9ipILOXm
KO4a5I+8R2QTH4BM0WaIKnv5jCHose/l9LL3
Y8MApsjP6gOWNM8b9aVTjBFnf0xEF7sOSBBB
E4G2/og5Fr+H8DYaotqgJ3nrzRfYA0gSXwwb
) ; key id = 49656
100 RRSIG DNSKEY 5 2 100 20090803071330 (
Figure 9: Example of a signed zone file
20090704071330 17000 example.net.
VQb1OdYAFpDk9kBPqkvuHL4W+e1Ulo/QzIOD
7EyeZfJHNYW8bGhyNY5uaXnf3o/tBE6tj8mY
1kmRJsBWQXdSjRlW3syaZD7+W93m3rS6/reI
9hBAijy2xSEEVx1LTeeLu1qzzD0HMootC/cw
DuWSISPcS+9YB0sUbVsGQdzxn7E= )
100 RRSIG DNSKEY 5 2 100 20090803071330 (
20090704071330 49656 example.net.
TpWicKxjdD5NML8pT+t1moSOGDQF+Nl4AbeO
oAher5Q8QCrx2JBiKcyi5iaTHZyg6RizFLPW
+FxfcSaMmzk0030Zu0ILlZwOAWUv4gxdmoBe
MQQ/4tuZp6Dgsh7OLl+3dU+S0QihyQUXDnkt
MKARs10tBGpuIkzpKJFBY5eEAsV9ivlXx1Wi
zrY4vMkth6NuasmpKJ0BYaonHUMwK8NzAQ== )
*.example.net. 100 IN A 192.168.2.10
100 RRSIG A 5 2 100 20090803071330 (
20090704071330 17000 example.net.
U6uEoNwJVPFcPgfoloQfDTMgGjqeLijMqr7Q
RlPufDoy6SEYswoJWBk1mqo1cCCkN05lNqmr
XD6Nr4Q6gRV/F8x41KiV+U1u0+bnV6yog5CM
XFudPKnrMJC4Cr9mzmUfeiqX3yaKjqr46noE
37B1KrmcjJAlTIuVbLJ2dyPMxvo= )
100 NSEC a.example.net. A RRSIG NSEC
100 RRSIG NSEC 5 2 100 20090803071330 (
20090704071330 17000 example.net.
hYQV/LI/Uo2uCTAlXigo0tmuxiFH+MNUL265
hsNY3CHcdy4qJWV/fnAjPaNcA/oQMnhqfnWT
JBjp6RqPlTUZHKMPx1R7UbSPQSpI35lt5niE
xDQS5LHH4H+tzuV+HazcBR9rqLhEncPqgVmq
qIpsQRiJlMYnpN2bSjsdoqlJOrM= )
a.example.net. 100 IN A 192.168.2.1
100 RRSIG A 5 3 100 20090803071330 (
20090704071330 17000 example.net.
MughSVso2OhRNFgUmI0iFmovjot4o0ZPTPnt
dZ/ef8WJoi2fCXutgz3nvQlQbWrI7sLetyCD
9oKZN15wISDW4inkrWqwT5RLvo5iagXfn7wv
CzZflPqYoDYD3XDfAbxzjlF5X8HiZQmQnQU2
PNOaVRj9I5OeiKBRKJaNPCTKXGU= )
100 NSEC b.a.example.net. A RRSIG NSEC
100 RRSIG NSEC 5 3 100 20090803071330 (
20090704071330 17000 example.net.
rO/aVFfYOUyk8NtiOAs2ypWuSarINWXedIoW
FTpeo3uUih900re52vlFMRay+ZanASfSS837
ic9SIVcZz3DpFhlIuDgsSEFNOzvEwptUnvCC
osDS6vgF0ZyxTW3SD4VNIStRlmxqoBD8S3kV
OxqJ0yoL0nBpskQ2UOzLawolIh4= )
b.a.example.net. 100 IN A 192.168.2.11
100 RRSIG A 5 4 100 20090803071330 (
20090704071330 17000 example.net.
SiYt5SIoXwmR83oxjg/rT8KzdciE8UW4tv0c
Figure 9: continued