DNSSEC HOWTO, a tutorial in disguise

Olaf Kolkman
Revision 134

July 4, 2009
____________________________________________________________________

Download the most recent PDF release from: http://www.nlnetlabs.nl/dnssec_howto/dnssec_howto.pdf

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 [354].

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

I  DNSSEC, the background
1 A motivation for DNSSEC
II  Securing DNS data
2 Configuring a recursive name server to validate answers
 2.1 Introduction
 2.2 Warning
 2.3 Configuring the caching forwarder
  2.3.1 Configuring a trust anchor
  2.3.2 How and where to get these trust anchors?
  2.3.3 Public repositories of trust-anchors
  2.3.4 Testing
 2.4 Finding trust-anchors
 2.5 Maintaining Trust Anchors
 2.6 Lookaside Validation
  2.6.1 Configuring lookaside validation
 2.7 Some Troubleshooting Tips
3 Securing a DNS zone
 3.1 Introduction
 3.2 Configuring authoritative servers
 3.3 Creating key pairs
  3.3.1 Key Maintenance Policy
  3.3.2 Creating the keys
 3.4 Zone-signing
 3.5 Caching forwarder configuration
 3.6 Zone Re-Signing
 3.7 Troubleshooting Signed Zones
 3.8 Possible problems
 3.9 Automating the signing process
4 Delegating of signing authority; becoming globally secure
 4.1 Introduction
 4.2 Practical steps
 4.3 Possible problems
 4.4 Registering with a DLV registry
5 Rolling keys
 5.1 DNS traversal
 5.2 ”Pre-Publish” and ”Double Signature” rollovers
 5.3 Tools
 5.4 ZSK rollover
  5.4.1 ZSK preparation (production phase)
  5.4.2 ZSK rollover (phase1)
  5.4.3 ZSK Cleanup (phase2)
  5.4.4 Modifying zone data during a rollover
 5.5 Key-signing key rollovers
  5.5.1 KSK preparation (production phase)
  5.5.2 ZSK rollover (phase 1)
  5.5.3 KSK cleanup (phase 2)
  5.5.4 Multiple KSKs
III  Troubleshooting tools
6 Using drill for troubleshooting
7 Using dig for troubleshooting
8 DNSSEC tools
IV  Securing communication between Servers
9 Securing zone transfers
 9.1 Introduction
 9.2 Generating a TSIG key
  9.2.1 Generating a TSIG secret with dnssec-keygen
  9.2.2 Other ways to generate secrets
 9.3 Configuring TSIG keys
 9.4 Primary servers configuration of TSIG
 9.5 Secondary servers configuration of TSIG
 9.6 Securing the NOTIFY message too
 9.7 Troubleshooting TSIG configuration
 9.8 Possible problems
  9.8.1 Timing problems
  9.8.2 Multiple server directives
V  Appendices
A Deploying DNSSEC: the Milestones
 A.1 Private Key policies and procedures
 A.2 Public Key policies and procedures
 A.3 Signing infrastructure
 A.4 Server infrastructure
 A.5 Monitoring tools
 A.6 Serving a Secured zone
 A.7 Requesting secure delegation
 A.8 Secure Delegation Provisioning
B BIND installation
C Estimating zone size increase
D Generating random numbers
E Example DNSSEC key procedure
F Perl’s Net::DNS::SEC library

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 users1 . 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).


PIC

Figure 1: DNS environment


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.2

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.


PIC

Figure 2: Trust anchors in the DNS tree


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.3

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. 4 . 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.


  

  // Trusted keys

  // These are examples only, do not use in production

  

  trusted-keys {

  "nlnetlabs.nl."  3 5

    "AQPzzTWMz8qSWIQlfRnPckx2BiVmkVN6LPupO3mbz7Fh

     LSnm26n6iG9NLby97Ji453aWZY3M5/xJBSOS2vWtco2t

     8C0+xeO1bc/d6ZTy32DHchpW6rDH1vp86Ll+ha0tmwyy

     9QP7y2bVw5zSbFCrefk8qCUBgfHm9bHzMG1UBYtEIQ==";

  

  "193.in-addr.arpa." 257 3 5

    "AwEAAc2RnCT1gjU22FbNC1baMQec77fq60z2HlCKscYl

     3idBZTp703ApMfAAFcMZQGkSmo8NP+47KqZJwG9ISLaT

     bUais3khgFVrf7lIRzPJAMlXHsmOMmpq5xBORF66EDt/

     u2dau3qqzOfb/BrKCklGgnwBosgqaSPmWBQTuzJFqzi3

     4FQIt4xFHWYyt3B5qZ9h4dpUL96etvvx1N+z8tlXjhlm

     Vauw1EPZnz2rmY6HEJFS2zjaI1FrDtY5/pooJjRWjobk

     RXL3iqjd5J/cmDikxjQCjwnbwBS+YvcwZCos4n9Xh2l5

     kf2kOcq9xCmZvEplfWJ9lWbVkfhpWaM8qXXPN8E=";

  

  

  "195.in-addr.arpa." 257 3 5

    "AwEAAaMN4kOrGaiHJBikvcf+mhPxzprL85Q40VA0hbRc

     a8FDDn6Xlkuj95Nizy2vMrOy1MjIjo7a+GACGp6C/Rdj

     6nDimsRrUBr/G/dq+zBgg8qvRXWJZhx+zNCgkfv9gs1B

     eRlPnjXr1K/x5viTzQRDK3SYfHiCMVNxuYN+T7kniDLx

     QRUI/ASF3YxqNQ+Oo+T5L6nYtO7uLeAUdxzToRdIHaey

     iSnq52boA/3Yg6X8Kbo1uAUpeU4QDD7bOwq+obmaToLU

     m/FvNUKx0l9U2P2ItcsqRCHQut/RxK2pj8GGRDCDco1J

     5UAi7hiwP1eEWmbigbPnDQg++QDjegV39vTJQ2c=";

  };   


Figure 3: trust anchor configuration


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 server5 . 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.


PIC

Figure 4: 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 6 mechanism called lookaside validation [1918].

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.


PIC

Figure 5: Trust anchors in the lookaside tree


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 [987], 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


  Usage:

      dnssec-keygen -a alg -b bits [-n type] [options] name

  

  Version: 9.5.0-P2

  Required options:

      -a algorithm: RSA | RSAMD5 | DH | DSA | RSASHA1 | HMAC-MD5 | HMAC-SHA1 | HMAC-SHA224 | HMAC-SHA256 |  HMAC-SHA384 | HMAC-SHA512

      -b key size, in bits:

          RSAMD5: [512..4096]

          RSASHA1: [512..4096]

          DH: [128..4096]

          DSA: [512..1024] and divisible by 64

          HMAC-MD5: [1..512]

          HMAC-SHA1: [1..160]

          HMAC-SHA224: [1..224]

          HMAC-SHA256: [1..256]

          HMAC-SHA384: [1..384]

          HMAC-SHA512: [1..512]

      -n nametype: ZONE | HOST | ENTITY | USER | OTHER

          (DNSKEY generation defaults to ZONE

      name: owner of the key

  Other options:

      -c <class> (default: IN)

      -d <digest bits> (0 => max, default)

      -e use large exponent (RSAMD5/RSASHA1 only)

      -f keyflag: KSK

      -g <generator> use specified generator (DH only)

      -t <type>: AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF (default: AUTHCONF)

      -p <protocol>: default: 3 [dnssec]

      -s <strength> strength value this key signs DNS records with (default: 0)

      -r <randomdev>: a file containing random data

      -v <verbose level>

      -k : generate a TYPE=KEY key

  Output:        K<name>+<alg>+<id>.key, K<name>+<alg>+<id>.private


Figure 6: dnssec-keygen arguments


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 files7

  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 secure8 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,9 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.


  ; example.net zone

  ;

  $TTL 100

  $ORIGIN example.net.

  @                       100     IN      SOA     ns.example.net. (

                                                  olaf.nlnetlabs.nl.

                                                  2002050501

                                                  100

                                                  200

                                                  604800

                                                  100

                                                  )

  

  

                          NS              ns.example.net.

  ns.example.net.         A               192.168.2.203

  

  a                      A               192.168.2.1

  b                      A               192.168.2.2

  

  

  *                      A               192.168.2.10

  b.a                    A               192.168.2.11

  

  

  ; These are the keys that need to be publised in the DNSKEY RRset

  ;

  $include Kexample.net.+005+17000.key    ; ZSK

  $include Kexample.net.+005+49656.key    ; KSK   


Figure 7: example.net example zone


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’ order10 .
  • 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.


  Usage:

   dnssec-signzone [options] zonefile [keys]

  

  Version: 9.5.0-P2

  Options: (default value in parenthesis)

   -c class (IN)

   -d directory

   directory to find keyset files (.)

   -g: generate DS records from keyset files

   -s [YYYYMMDDHHMMSS|+offset]:

   RRSIG start time - absolute|offset (now - 1 hour)

   -e [YYYYMMDDHHMMSS|+offset|"now"+offset]:

   RRSIG end time  - absolute|from start|from now (now + 30 days)

   -i interval:

   cycle interval - resign if < interval from end ( (end-start)/4 )

   -j jitter:

   randomize signature end time up to jitter seconds

   -v debuglevel (0)

   -o origin:

   zone origin (name of zonefile)

   -f outfile:

   file the signed zone is written in (zonefile + .signed)

   -I format:

   file format of input zonefile (text)

   -O format:

   file format of signed zone file (text)

   -N format:

   soa serial format of signed zone file (keep)

   -r randomdev:

   a file containing random data

   -a: verify generated signatures

   -p: use pseudorandom data (faster but less secure)

   -t: print statistics

   -n ncpus (number of cpus present)

   -k key_signing_key

   -l lookasidezone

   -z: ignore KSK flag in DNSKEYs

  Signing Keys: (default: all zone keys that have private keys)    keyfile (Kname+alg+tag)


Figure 8: dnssec-signzone arguments



  ; 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



                                          B3Yl4+wFsQNb0M5pDBBP4Z2WIs+FDaP3xW7x

                                          jFHuZyAl85yY0W6jP8nwWeNcvHcAAmhzYRT7

                                          Isn2PKU92832xoIG9kF9Z3A6p3s= )

                          100     NSEC    b.example.net. A RRSIG NSEC

                          100     RRSIG   NSEC 5 4 100 20090803071330 (

                                          20090704071330 17000 example.net.

                                          KKIwCnO6wrYueT9ReasVJEXBYlhjoii/QB+7

                                          cJAGpsxmV7dIgd2jEp8PTmdRaW6aYIPBn3nR

                                          tIzhyNorFhocEVyBqAuPF7D58QJcJy78PA1W

                                          6WG/5vGOWLKGMwWnLn1zBPcqifPC9BiQTyeU

                                          dVASF1x+aN2QFZCKLGHAatwloG8= )

  b.example.net.          100     IN A    192.168.2.2

                          100     RRSIG   A 5 3 100 20090803071330 (

                                          20090704071330 17000 example.net.

                                          OnXyjrZUOnfW9byUBdHQbsx1JaWWZTHTmjoA

                                          59zCJDSlp8Ez/+UIoBHPfrxRMt//yRtIDjT0

                                          fDacjTKVJ6YeRLmCEwCptYGp9MtqoL5xlleH

                                          GD/Awido8GrWfGsBEr7GUbcgPKDCeNnVzyok

                                          PnG5YAG5ZilgOJh9PXijFGIHcxY= )

                          100     NSEC    ns.example.net. A RRSIG NSEC

                          100     RRSIG   NSEC 5 3 100 20090803071330 (

                                          20090704071330 17000 example.net.