Paranoid Penguin - DNS Cache Poisoning, Part II: DNSSEC Validation

Configure your DNS server to check zone signatures using DNSSEC.

Last month, I described, in detail, the problem of DNS cache poisoning and why it's fundamentally changed our understanding of DNS security. Whereas previously it seemed good enough to keep one's DNS server patched and limit the hosts for which it performed recursive queries and zone transfers, we now have no choice but to pay attention to the authenticity of DNS data that our local resolvers and recursing DNS servers receive from other servers.

This is because the way DNS recursion works makes it too easy for an attacker to trigger events that lead directly to that attacker's injecting forged DNS data into a recursing server's cache, resulting in all users who rely on that server being redirected to impostor “evil twin” sites for specific e-commerce and on-line banking sites, or malicious, malware-spreading Web sites and so forth.

I concluded last month by explaining that although the short-term fix to Kaminsky's cache-poisoning attack is to patch DNS software so that recursing servers randomize their source UDP ports for DNS queries, this only makes the attack take longer (albeit, much longer); it doesn't eliminate it as a threat. The best protection, rather, is for administrators of authoritative DNS servers to sign all their zone data cryptographically, and for administrators of recursing or caching DNS servers to configure their servers to check the signatures of all signed zones they come across.

All of this signing/validating functionality is achieved by way of DNSSEC, a set of extensions to the DNS protocol. Most modern DNS server software packages now support DNSSEC (with djbdns as the most notable exception).

This month, I explain how to configure your recursing/caching DNS server to check DNS zone data signatures. Because the Internet Software Consortium's BIND package is by far the most popular DNS server application for UNIX and UNIX-like systems, my examples all involve BIND.

If you administer your own DNS zones, you also should sign your own zones and publish your certificates and signatures, but that's out of scope for this article. (See Resources for links to other DNSSEC information and tutorials. I may cover zone signing and DNSSEC key management in a future column as well.)

Note that my preferred Linux server distribution nowadays is Ubuntu Server 10.10, so my examples all apply directly to Ubuntu and other Debian derivatives. If you run some other distribution, my examples still should be useful, because the only peculiar thing Ubuntu and Debian do in how they package BIND is to break up its configuration file (named.conf) into several parts (named.conf.options, named.conf.local and named.conf.default-zones) that are read into named.conf via “include” statements.

DNSSEC Overview

Mainly what I want you to get out of this article is how to enable DNSSEC validation on your BIND-based nameserver. I probably could fill most of this space with an overview of what DNSSEC is, how it works and so forth, but in the interest of conciseness, I give the low-attention-span version instead.

DNSSEC is a Public Key Infrastructure (PKI) for DNS zone data. When a zone administrator digitally signs all of the different types of Resource Records (RRs) in a given zone, and publishes those signatures and the zone's signing key's public certificate, it then becomes possible for any recursing nameserver that makes queries against that zone to validate those signatures and, therefore, to have cryptographic proof that the answer to a given DNS query hasn't been forged or tampered with.

This probably doesn't sound simple to begin with, but in practice, it's much more complicated even than that. This is because DNS is both hierarchical and distributed, with a “root” zone at the top and individual hostnames and other Resource Records at the bottom. In between are layers of zones and subzones.

Consider the top-level domain (TLD) .us as an example. It consists of more than 50 subzones, each representing a different state or protectorate in the United States of America—for example, for Minnesota, for Wisconsin and so forth. Within each “state” subzone there can be hundreds of sub-subzones representing cities, counties, state or municipal government agencies and so forth., for example, is used by public libraries in the state of Minnesota, and is used by the Saint Paul Public Library system.

Suppose I'm the DNS administrator for, and I sign all of the records in that zone and publish the corresponding RRSIG, DNSKEY and other related records. How praiseworthy of me!

However, if someone tries to resolve names in my domain, for example,, they'll speak to as many as four other nameservers before they make it all the way down the hierarchy to my beautiful, signed zone—that is, the respective authoritative nameservers for “.” (the root zone), .us, and What's to stop someone from tampering with the answer to one of those prior, recursive queries? (Who's authoritative for .us? Who's authoritative for Who's authoritative for

Obviously, there has to be a “chain of validation” all the way from the zone I really want to validate (, all the way up to the root domain. As it happens, “.” root is signed, and I'll show you how to download and verify the initial root key shortly. So are .us and However, isn't yet signed (at the time of this writing). Does that mean it's pointless to sign zones below that?

Not at all. The Internet Software Consortium, creators and maintainers of BIND, maintain a DNS Look-aside Validation (DLV) database of keys for zones having precisely this sort of gap in their chains of validation. If I sign and register my key-signing key with, resolving nameservers that are configured to use DLV still will be able to construct a complete enough chain of validation by seeing that vouches for the validity of my key-signing key, which actually is used to sign the keys (zone-signing keys) with which I actually sign zone data.

In recent versions of BIND, DNS Look-aside Validation is not only enabled by default, but preconfigured as well.

There's just one more DNSSEC mechanism I should describe before diving in to nameserver configuration, and that's automated key management. I alluded to there being two kinds of DNS keys: key-signing keys (KSKs) and zone-signing keys (ZSKs). Both types of keys must be regenerated periodically—every few months in the case of ZSKs, with which you actually sign zone data (although in my opinion, the need to do so does not speak well of how securely PKI is implemented in DNSSEC). Naturally, every time you change a KSK or ZSK, you must re-sign your entire zone.

Saying that this makes zone-signature management a bit of a headache is a gross understatement; however, there are various ways to automate this process. Luckily, right now you and I are concerned only with validating keys, not maintaining them, and recent versions of BIND 9 have a mechanism for automatically checking and updating a caching nameserver's cache of DNS keys.

This is the managed-keys{} statement in named.conf, which can be used in lieu of the static trusted-keys{} definition. When you set up BIND with the root zone's signing key, you'll do so using a managed-keys{} statement that specifies an “initial” key that is itself not a KSK or ZSK, but is used in a transparent, cryptographic transaction in which your nameserver queries a root zone authority for a copy of its current public ZSK and caches the answer it receives.

But I'm getting a little ahead of myself. Let's set up a caching nameserver and then enable DNSSEC validation on it.