Basic DNSSEC with BIND 9.9

Everybody knows that DNS is insecure, and DNS Security Extensions (DNSSEC) is supposed to fix that. I know that several of my readers consider DNSSEC suboptimal, but it’s the standard, so we get to live with it. I recently got DNSSEC working on BIND 9.9. As I write this 9.9 is in Release Candidate state, but the functionality should be basically unchanged. My goals for DNSSEC on BIND were to manually edit my zone files, but have the DNS server maintain the keys. BIND 9.9 makes this possible.

This is a limited example of how to get basic DNSSEC working. To use it, your registrar must support DNSSEC. There’s ways around this, such as DLV, but they’re out of scope for this document. Also note that I’m not covering key rotation. That’ll be a future post.

You also must have a domain whose parent is signed. The root zone, .com, .net, and .org are all signed, but not all top-level domains are signed. Verify your particular TLD before proceeding. Again, you can use DLV for these orphaned domains, but that’s out of scope for this document.

I’d also suggest that you read the BIND 9.9 ARM first. But if you were going to bother to do that, you wouldn’t have done the Google search to find this article.

You will almost certainly have service interruptions as you learn DNSSEC. I strongly recommend that you set up a test server for your DNSSEC testing. Move a test domain to it. You cannot test DNSSEC on a private domain; it must be a real, Internet-facing domain. Configure dnssec validation on this test server.

You also need a server that provides DNSSEC resolution, but will not be authoritative for your test domain. I’m assuming that you configure DNSSEC resolution on your production server. If you only have one DNS server, you can use an offsite public resolver such as unbound.odvr.dns-oarc.net. (Note that Google DNS, like most public DNS servers, does not validate DNSSEC.)

Verify that DNSSEC resolution works on both servers with dig(1).

$ dig www.isc.org +dnssec

; <<>> DiG 9.8.1-P1 <<>> www.isc.org +dnssec
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28734
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 5, ADDITIONAL: 13

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;www.isc.org. IN A

;; ANSWER SECTION:
www.isc.org. 600 IN A 149.20.64.42
www.isc.org. 600 IN RRSIG A 5 3 600 20120305233238 20120204233238 21693 isc.org. IKekIJVV99bkTYw4L2KG/xZpQ+BYlCK0IDSsWXKZRD8ceR/VNcfNFxV2 5VK51Fqmy...
...

Two interesting things here. First, the ad flag indicates that this is “authenticated data,” also known as DNSSEC-validated. Second, the RRSIG (Resource Record Signature) is the actual DNSSEC signature. isc.org is DNSSEC-validated.

DNSSEC generates a lot of key files. You don’t edit these key files by hand, and you rarely look at their contents, so use a separate directory. If you have a lot of zones, you’ll want a separate directory for each zone.

You’ll need a directory for keys.

$ mkdir /etc/namedb/keys

To start you need a “master” key to sign other keys with (the Key Signing Key, or KSK), and then a key for each zone (the Zone Signing Key, or ZSK). Your nameserver must be able to read these keys.

# dnssec-keygen -f KSK -a RSASHA1 -b 2048 -n ZONE example.net
Generating key pair…………………………………………………………………………………………………………………………………………….+++ ……………………..+++
Kexample.net.+005+38287
# dnssec-keygen -a RSASHA1 -b 2048 -n ZONE example.net
Generating key pair………….+++ ..+++
Kexample.net.+005+55896
# chown bind:bind *

We’ve generated two key files: Kexample.net.+005+38287 (the KSK) and Kexample.net.+005+55896 (the ZSK).

Now that you have keys, let’s look at configuring named and the zone itself.

I recommend you enable DNSSEC logging in named.conf. If you have trouble, the DNSSEC log will identify the problem. (Actually Understanding the log is left as an exercise for the reader, the ARM, and their favorite search engine.) Make a separate directory for the log.

# mkdir /etc/namedb/log
# chown bind:bind /etc/namedb/log

Then add a logging stanza in named.conf. With this configuration, the log file will never grow larger than 20Mb.

logging {
channel dnssec_log {
file "log/dnssec" size 20m;
print-time yes;
print-category yes;
print-severity yes;
severity debug 3;
};
category dnssec {
dnssec_log;
};
};

Now set up a zone. Here I add DNSSEC data to my test domain.

zone example.net {
type master;
file "master/example.net";
key-directory "keys/";
inline-signing yes;
auto-dnssec maintain;
};

Reload your nameserver. You’ll now see the following files in the zone file directory:

example.net
example.net.jbk
example.net.signed
example.net.jnl

Inline signing works by taking the zone file you manually maintain, transforming it into a dynamic zone, and signing the dynamic zone. DNSSEC changes are made to the journal file. As a result of this, the serial number shown to the world can differ from the serial number in your file. That’s a minor change that I’m perfectly happy to live with.

You should now see RRSIG records in your test zone. You will not see the AD flag, however. You never see an AD flag for a zone on its authoritative nameserver.

So, how do you test DNSSEC on your domain? You might try your second nameserver. It won’t show the AD flag either, but it should also show the RRSIG records.

DNSSEC works via a chain of digital signatures. The root zone is signed, and your server knows about that signature. Most delegations beneath root are also signed. Your parent zone doesn’t know to trust your KSK until you tell it. This is where your registrar comes in. Create a delegation signature key (DSKEY) from your KSK.

# dnssec-dsfromkey Kexample.net.+005+38287
example.net. IN DS 38287 5 1 E8C01C990ACC8CEDF48379EDF9EDAB5389A9CB4E
example.net. IN DS 38287 5 2 57EC9364CEAE50B17C0C251950B4E5B8870F6A479A94C3A92359A623 39703D53

Copy these two lines and paste them into your registrar’s DSKEY interface. Your registrar might take one or both types of DSKEY records. I found that GoDaddy took both, but I had to remove the space from the SHA-256 (second) record.

When your registrar updates the TLD’s zone, DNS servers that are not your authoritative zone will return the DS flag. You’ll have functioning DNSSEC.

(Thanks to Jeffry A. Spain for his invaluable hints in debugging my first DNSSEC setup.)

7 comments to Basic DNSSEC with BIND 9.9

  • […] you were thinking about implementing DNSSEC, Michael Lucas did it himself and wrote down his notes.  You can read them and either follow along to implement it yourself, or […]

  • Tony

    One thing that got me for a while – gandi wants the contents of the .key file *not* the DS record. It also doesn’t complain if you copy/paste the wrong thing in…

  • ranpha

    Does this guide works with BIND 9.8? Because I get the error:

    /etc/named.conf unknown option ‘inline-signing’

    when trying to restart the service. Is inline-signing a BIND 9.9-only option?

  • Ranpha, nope. Bind 9.9 and above only.

  • dkoleary

    Hey; Thanks for posting this. This page and others like it are finally clarifying dnssec for me. Two questions: (1) Should we be generating keys for in-addr.arpa zones too? and (2): dnssec log file reading. You mentioned the ARM. what’s that? A few google searches haven’t resulted in anything.

    Thanks again for posting this. I appreciate it.

    Doug O’Leary

  • Doug,

    You can and should dnssec in-addr.arpa as well. But forwards are a start.

    The ARM is the BIND Administrator’s Reference Manual… used to be called the BOG.

  • ranpha

    Ok, after struggling with shoving BIND 9.9 on CentOS 6, I managed to get it to work. WIth this, does key rollover still need to be done manually?