Newer
Older

Overview of DNSSEC

Date: 2024-09-01 01:35
Tags: dnssec, dn42

I recently set up basic DNS with DNSSEC on DN42 and it shocked me how all DNSSEC tutorials - and tools - seem to suck. So here is some information. Tools might come later. This isn't a tutorial. I assume you already know how digital signatures work.

How DNS works

DNS is a hierarchical, delegated system. If you control a domain name like "immibis.com", you can select which nameserver is used to look up all domains under "immibis.com", although most people outsource this to a nameserver that belongs to their domain registrar, which is fine too.

A full lookup for the IP address of "foobar.example.immibis.com." (real DNS names always end with a dot) will go like this:

  1. Client picks a DNS root server, e.g. "a.root-servers.net." (2001:503:ba3e::2:30)
  2. Client asks 2001:503:ba3e::2:30: what is the IP address of "foobar.example.immibis.com."?
  3. 2001:500:d937::30 responds: the nameserver for "com." is "l.gtld-servers.net." and its address is 2001:500:d937::30
  4. Client asks 2001:500:d937::30: what is the IP address of "foobar.example.immibis.com."?
  5. 2001:500:d937::30 responds: the nameserver for "immibis.com." is "dns1.registrar-servers.net." and its address is 2610:a1:1025::200
  6. Client asks 2610:a1:1025::200: what is the IP address of "foobar.example.immibis.com."?
  7. 2610:a1:1025::200 responds: I am the authority for that domain, and it doesn't exist. (If we asked it for "www.immibis.com." we'd get an address back)
Notice that delegation points aren't always at the dots. 2610:a1:1025::200 didn't give the client a different nameserver address for "example.immibis.com." because that isn't managed by a different organization from "immibis.com." It's the same server, and it knows the domain doesn't exist. If there was a delegation point several layers down, 2610:a1:1025::200 could give us a nameserver for "foo.bar.baz.immibis.com." directly instead of making us traverse intermediate steps.

Each piece of information served by DNS is called a "record". An example record says "the nameserver for com. is l.gtld-servers.net." Another record says "the address of l.gtld-servers.net. is 2001:500:d937::30." Usually more than one record of the same type can exist, called an RRset (resource record set) and usually one is chosen arbitrarily ("com." has many nameservers and each one has many addresses).

The set of records managed by a DNS server (loosely speaking) is called a "zone". A zone is named after its top-level node, or "apex". The top-level zone contains a "com." record which points to the nameservers of the "com." zone. The "com." zone contains an "immibis.com." record which points to the nameservers of the "immibis.com." zone. "example.immibis.com." is not a zone in this example, although it could have been.

How DNSSEC works

DNSSEC authenticates the information the nameserver gives out, not the nameserver itself. This means it is possible to offline-sign every piece of information the nameserver could possibly give out, and the server doesn't have to have any private keys. This also means it is possible for any random server, such as an ISP's cache, to give out YOUR authenticated DNS information to clients.

There are basically three main parts to DNSSEC.

  • Signing the records in a zone
  • Recording the keys used for signing
  • Linking the zone to its parent

First of all, the records in the zone are signed. An RRSIG record is generated from each record and an NSEC or NSEC3 is generated from each gap between records. The combination of these allows the nameserver to provide a signed answer to any possible query, whether it refers to an existent record or not, even if the nameserver doesn't have the private key. Note: NSEC records allow clients to enumerate all the names in the zone, by noting where the gap ends and then advancing to the next one.

Second, you manually add DNSKEY records to your zone, which are the full public keys used to sign any part of the zone. Each one has an ID number, and each signature references the ID number of the key that signed it. There are a couple of flag bits too.

DNSKEY records are also signed, so in reality, you do this before you sign the zone. Any record can be signed by any key in DNSKEY (with the appropriate flag set) but the DNSKEY records must be signed by a single key. This key is the one that gets linked to the parent. You can use the same key to sign all records including DNSKEYs, or you can use one key to sign DNSKEYs and a different key (or more than one) to sign the rest. This two-stage system allows the use of various key rotation and offline signing schemes, if desired.

Third, the hash of the key that signed your DNSKEYs must be added to the parent zone in a DS record.

Extra

The key that is linked to the parent is called a "secure entry point" or SEP. A client is allowed to pin an SEP or its hash, even if the parent zone doesn't contain it. This is called an "island of security" and not relevant on most of the Internet any more. There may be more than one SEP.

SEPs SHOULD have the SEP flag (bit value 1, bit number 15 since the IETF counts the MSB as bit 0) set, but it wasn't required in earlier versions of the RFC, so clients must not refuse to use SEPs that don't. Keys that sign other records must have the Zone Key flag set (bit value 256, bit number 7) and clients MUST check this.

How a client resolves an IP address with DNSSEC

(this time I won't write out actual addresses and keys)
  1. Client picks a DNS root server, say, ADDR1. It knows the public key KEY1 (ID 11111).
  2. Client asks ADDR1: what is the IP address of "foobar.example.immibis.com."?
  3. ADDR1 responds: the nameserver for "com." is "NS2" and its address is ADDR2 and the hash for the zone key is HASH2 and its ID is 12345. Here are the signatures for these records, using key 11111.
  4. Client validates signatures with KEY1.
  5. Client asks ADDR2: what are the keys for "com."?
  6. ADDR2 responds: they are KEY2A (12345) and KEY2B (54321). Here are the signatures for these records, using key 12345.
  7. Client validates HASH2 matches the hash of KEY2A, and validates signatures with KEY2A.
  8. Client asks ADDR2: what is the IP address of "foobar.example.immibis.com."?
  9. ADDR2 responds: the nameserver for "immibis.com." is "NS3" and its address is ADDR3 and the hash for the zone key is HASH3 and its ID is 54321. Here are the signatures for these records, using key 54321.
    (Note that key ID numbers are specific to each zone. Key 54321 in "immibis.com." is different from key 54321 in "com.")
  10. Client validates signatures with KEY2B.
  11. Client asks ADDR3: what are the keys for "immibis.com."?
  12. ADDR3 responds: they are KEY3 (54321). Here is the signature for these records, using key 54321.
  13. Client validates signatures with KEY3.
  14. Client asks ADDR3: what is the IP address of "foobar.example.immibis.com."?
  15. ADDR3 responds: I am the authority for that domain, and it doesn't exist. Here is the NSEC record showing there is nothing between "examcheats.immibis.com." and "exoskeletonfactory.immibis.com." Here is the signature for this record, using key 54321.
  16. Client validates signatures with KEY3.

How do I actually do these things?

Good question. dnssec-tools kind of suck, unless you want to use the exact workflow they were designed for. You should still use dnssec-tools unless you know a better alternative.