Plain DNS believes the first plausible answer it hears. DNSSEC lets the owner of a zone sign its records, so that a validating resolver can check with arithmetic, not faith, that an answer came from that owner and was not changed on the way. Each zone's key is vouched for by its parent, all the way up to one key at the root. This chapter assumes you know how names, servers and caches fit together; if not, start with networks · DHCP & DNS.
Common mix-up: DNSSEC does not encrypt anything. A signed answer still crosses the network in plain text, readable by anyone on the path. DNSSEC is a tamper-evident seal, not an envelope; hiding your lookups is the job of encrypted DNS (Chapter 12). And the padlock in your browser is TLS, a separate system with separate keys.
A resolver that sends a question over UDP gets back a packet that could have come from anyone able to guess a few numbers in time. Chapter 13 covers how cache poisoning exploits that. The fix that removes the guessing game entirely is to make answers checkable: the zone's owner signs each set of records with a private key, publishes the matching public key, and any resolver can verify the signature. A forger can copy a signature, but cannot make a new one for different data.
RFC 4033, the overview of DNSSEC, lists exactly three things it provides. Data origin authentication: the records were published by whoever holds the zone's key. Data integrity: they were not altered after signing. Authenticated denial of existence: when the answer is "no such name" or "no such record type", that answer is signed too, so it cannot be forged either. RFC 9364, the current best-practice summary, points back to the same three.
Everything else is out of scope, and most DNSSEC confusion comes from expecting one of the missing items. The table is worth reading row by row.
| Question | Does DNSSEC answer it? | Why |
|---|---|---|
| Who published this? | Yes | Only the holder of the zone's private key can make a signature that verifies |
| Was it changed? | Yes, detected | Changing one bit of a signed record makes its signature fail |
| Does it really not exist? | Yes | NSEC and NSEC3 records sign the gaps between names |
| Can others see my lookups? | No | Nothing is encrypted; see Chapter 12 |
| Will the site load? | No promise | A broken signature makes the name fail on purpose (SERVFAIL) |
| Is the content honest? | No | A signature proves who said it, not that it is true; a hijacked registrar account can publish signed nonsense |
| Is my laptop's copy safe? | Only sometimes | Usually the resolver validates, and the last hop to your device is unprotected |
Most phones and laptops run a stub resolver: a small client that forwards every question to a recursive resolver and believes what comes back. In the usual deployment the recursive resolver does the validating. It sets the AD (Authentic Data) bit on answers it has proven secure. But the AD bit is just a bit in a packet, and anyone who can forge the answer can set it too. RFC 4035 (section 4.9.3) says a stub must not rely on validation done on its behalf unless it got the answer from a trusted resolver over a secure channel. That is one of the reasons encrypted DNS and local validation both matter.
Three flags matter here. DO (DNSSEC OK) lives in the EDNS part of a query and says "send me the signatures too"; without it a server leaves the RRSIG records out. AD in a reply means "I validated this". CD (Checking Disabled) in a query says "give me the data even if validation fails, I will check it myself"; it is also the switch every DNS engineer flips first when a name returns SERVFAIL, to see whether DNSSEC is the reason. RFC 6840 refined the rules: a resolver should only set AD in a reply when the query carried DO or AD. Where the bits sit in the header is Chapter 2's business.
DNSSEC adds no new servers and no new protocol messages. It adds record types, defined in RFC 4034, that travel in ordinary DNS answers.
Most zones use two keys with different jobs. The key-signing key (KSK) signs only the DNSKEY RRset; its hash is what goes up to the parent as the DS. The zone-signing key (ZSK) signs everything else. The split exists for convenience, not cryptography: you can change the ZSK as often as you like without talking to the parent, because the parent only knows about the KSK. A KSK has flag value 257 (the "secure entry point" bit set); a ZSK has 256. Some operators use one key for both jobs, a combined signing key, and that is perfectly valid.
Here is what a signed answer looks like. The data is simulated, on the reserved name example.test, but the format is exactly what dig +dnssec prints.
; dig +dnssec www.example.test A (simulated answer) ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2 ; EDNS: version: 0, flags: do; udp: 1232 www.example.test. 3600 IN A 192.0.2.10 www.example.test. 3600 IN RRSIG A 13 3 3600 20261029120000 20261022110000 41522 example.test. kD9w3x… ; RRSIG fields: type covered (A), algorithm (13), labels (3), original TTL, ; expiration, inception, key tag (41522), signer name, then the signature
A signature has to be over bytes, and two servers must produce the same bytes for the same records, or verification would fail at random. RFC 4034 section 6 defines a canonical form: names in lowercase, uncompressed, the TTL replaced by the "original TTL" stored in the RRSIG (so a cache counting the TTL down does not break the signature), and the records of an RRset sorted by their data bytes.
The signed blob is the RRSIG's own fields (type covered, algorithm, labels, original TTL, expiration, inception, key tag, signer name) followed by every record of the RRset in canonical form. The signature field is then appended. The validator in Instrument 1 builds exactly these bytes, signs them with ECDSA P-256 (algorithm 13, RFC 6605) through your browser's WebCrypto, and verifies them the same way a resolver would.
The key tag algorithm (RFC 4034, Appendix B) is a simple checksum over the DNSKEY's data. It is not unique: two keys can collide, so a validator must try every key with a matching tag rather than trusting the tag as an identity.
A signature is only as good as your confidence in the public key that checks it. If a resolver fetched example.test's DNSKEY over the same unprotected channel as everything else, a forger could just send their own key with their own signatures. DNSSEC solves this by asking the parent. Validating www.example.test goes like this:
Every link is either a hash comparison (DS against DNSKEY) or a signature check (RRSIG against DNSKEY). Break any one and the chain stops there. That is the whole design.
The root zone was signed in July 2010, and its key has been replaced twice since. The first root KSK rollover, from the 2010 key to KSK-2017 (key tag 20326), happened on 11 October 2018, after a one-year delay while ICANN studied how many resolvers still had only the old anchor. The second, to KSK-2024 (key tag 38696), happened on 11 October 2026, eleven days before this chapter was written. A resolver that never learns the new anchor stops validating anything at all, so rollovers at the root are planned years ahead.
Most resolvers learn new anchors automatically with RFC 5011. When the root publishes a new KSK in its DNSKEY set, signed by the old one, a resolver following RFC 5011 notices it, waits out an "add hold-down" of at least 30 days while it keeps seeing the new key, and only then trusts it. The waiting is the safety: someone who briefly stole the old key could not slip in a new anchor without the change being visible for a month.
Worked example: check the real root anchor yourself. Below is the public key of the root's current KSK, KSK-2024, exactly as IANA publishes it in root-anchors.xml. The button builds the DNSKEY data (flags 257, protocol 3, algorithm 8), prefixes the root's name (a single zero byte), hashes it with SHA-256 in your browser and computes the key tag. Compare the result with IANA's published digest.
; press the button
Three simulated zones, ., test. and example.test., each with its own KSK and ZSK, generated fresh in your browser when the page loaded. Every RRSIG below is a real ECDSA P-256 signature over the canonical bytes, and every DS is a real SHA-256 digest. The validator walks the chain the way a resolver does. Change the trust anchor, swap the DS, tamper with the answer in transit or move the clock past the signatures' expiration, and watch which link fails and why. None of this touches the network.
Simulated zones on reserved names; times are simulated, starting 22 October 2026 12:00 UTC. The leaf zone's signatures expire after 7 days, test.'s after 20, the root's after 13.
RFC 4033 gives every answer a validating resolver handles one of four states, and the difference between them is the most practical thing in this chapter.
| State | Meaning | What the client sees |
|---|---|---|
| Secure | An unbroken chain of signatures and DS links from a trust anchor to this data | The answer, with the AD bit set |
| Insecure | The chain proves, with a signed denial, that some delegation on the way has no DS: the zone is simply unsigned | The answer, without AD. Most of the DNS is in this state |
| Bogus | There should be a valid chain, and there isn't: a bad signature, an expired one, a DS that matches no key, missing RRSIGs | SERVFAIL. The data is withheld |
| Indeterminate | No trust anchor covers this name, so there is nothing to check against | The answer, without AD |
"Insecure" sounds alarming but is ordinary: it means "provably unsigned", and the resolver treats the answer like plain DNS. "Bogus" is the alarm. A validating resolver refuses to hand out bogus data, because it cannot tell an attack from a mistake, and handing out data that might be forged would defeat the point. So a DNSSEC mistake looks, to a user, exactly like an outage: the site "doesn't exist", while friends on a non-validating network load it fine.
Two tools make this less mysterious. Extended DNS Errors (RFC 8914) let a resolver attach a reason code to the SERVFAIL: 6 is "DNSSEC Bogus", 7 "Signature Expired", 8 "Signature Not Yet Valid", 9 "DNSKEY Missing" (a DS exists, but no matching key), 10 "RRSIGs Missing". And the CD bit lets you ask the same resolver to skip validation. If +cd makes the answer appear, the problem is the signatures, not the servers.
; dig www.example.test A (simulated: the zone's signatures expired) ;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 4243 ; EDE: 7 (Signature Expired) ; dig +cd www.example.test A (same resolver, checking disabled) ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4244 www.example.test. 3600 IN A 192.0.2.10
Signature validity is checked against the resolver's own clock. A resolver whose clock is days wrong sees good signatures as expired or not yet valid; this is a real cause of "DNSSEC broke everything" on small devices that boot without a correct time. Signers therefore backdate the inception by an hour or so to absorb skew, and re-sign well before expiration: a common habit is to sign for a few weeks and refresh at the halfway point.
Most DNSSEC outages in the wild are not attacks at all. They are signatures that were allowed to expire because the signing job stopped, or DS records that no longer match the zone's keys. Both show up instantly in public checkers such as DNSViz and the Verisign DNSSEC Analyzer, which draw the same chain as Instrument 1 for real zones.
Signing records that exist is easy. Signing "this name does not exist" is harder, because there are infinitely many names that don't exist and the signer cannot sign each one in advance, and a server that signs on demand has to keep its private key online. DNSSEC's answer is to sort the zone's names and sign the gaps between them.
Sort every name in the zone in canonical order (RFC 4034 section 6.1: compare labels from the right, as lowercase bytes). Then give each name an NSEC record that says "the next name after me is X, and I hold these record types". If you ask for cat.example.test and the zone has blog and then mail, the signed NSEC at blog saying "next is mail" proves nothing lies between them. Its type list also proves "no such type" answers: the NSEC at mail listing only A proves there is no AAAA there. The resolver also needs one more NSEC proving no wildcard (*.example.test) could have produced an answer.
NSEC has a side effect: anyone can follow the chain of "next" pointers and list every name in your zone. This zone walking takes one query per name. For many zones that doesn't matter (the names are in certificates and search engines anyway), but some registries consider their list of customers confidential.
NSEC3 (RFC 5155) replaces each name with a hash of it before sorting. The chain now runs between hashes, so walking it gives you a list of hashes, not names. But hashes of short, common names can be guessed offline: hash www, mail, vpn and a few thousand more and see which match. NSEC3 originally allowed extra hash iterations and a salt to slow that guessing down. In practice the extra work fell mostly on resolvers and authoritative servers, an attacker with a graphics card shrugged it off, and RFC 9276 now says: iterations 0, no salt, and use plain NSEC unless you have a reason not to.
Because an NSEC record proves a whole range is empty, a resolver that has validated one can answer other questions in that range itself, without asking the authoritative server again. RFC 8198 allows exactly this "aggressive use" of the cache. It cuts the load from junk queries for random names, and it improves privacy a little, since fewer questions leave the resolver.
The sorted chain also lets the zone be signed offline, once, with the private key kept away from the servers. Some large operators prefer the opposite trade, signing on the fly with "minimally covering" records (RFC 4470) or the "black lies" style of answer, which avoid zone walking at the cost of keeping keys on every server.
NSEC3 has an opt-out flag, meant for huge zones like a top-level domain where most delegations are unsigned: unsigned delegations can be skipped from the chain. RFC 9276 says not to use it for small zones.
A simulated zone, example.test, with nine names. Ask for any name and type, and the explorer finds the records a signed server would send to prove the answer, using real canonical ordering for NSEC and real NSEC3 hashing (SHA-1 over the name in wire format, then the salt, repeated for each extra iteration, written in base32hex). Then walk the zone, and try guessing its names offline.
Keys get replaced: on a schedule, after a staff change, when moving to a better algorithm, or when moving to a new DNS provider. The difficulty is caching. At any moment, resolvers around the world hold copies of your DNSKEY set, your signatures and your parent's DS, each fetched at a different time and each expiring on its own TTL. A rollover is safe only if every combination a resolver could be holding still validates. RFC 6781 describes the standard methods and RFC 7583 works out their timing in detail.
Talking to the parent used to mean a web form at your registrar. RFC 7344 added CDS and CDNSKEY: records the child publishes in its own signed zone saying "this is what my DS should be". A parent that supports them polls the child and updates the DS itself, which makes KSK rollovers routine. RFC 8078 extends the idea to turning DNSSEC on or off.
The classic outage is changing DNS provider while the zone is signed. The new provider signs with its own keys, the DS at the parent still points at the old provider's KSK, and from the moment resolvers fetch the new keys every validating resolver returns SERVFAIL. The safe way is either to remove the DS first and wait out its TTL (going briefly insecure), or to have the two providers cooperate and publish each other's keys, the multi-signer model of RFC 8901. Instrument 3 shows both.
Pick a procedure, set the TTLs, and choose how long to wait between steps. The planner works out, hour by hour, whether some resolver somewhere could hold a combination of cached records that no longer validates, and marks those hours as bogus. It assumes the worst case: some resolver fetched each record at the worst possible moment. Real plans also add a margin for propagation to secondary servers and for the parent's own publishing delay.
Each DNSKEY names its algorithm by number. For years the guidance lived in RFC 8624. In November 2025 RFC 9904 obsoleted it and moved the official recommendations into IANA's registries, so they can change without a new RFC; RFC 9905, published alongside it, deprecated SHA-1-based signing. The values below are the ones RFC 9904 placed in the registry, as updated by RFC 9905.
| Algorithm | Number | Use for signing | Notes |
|---|---|---|---|
| ECDSAP256SHA256 | 13 | Recommended | Small keys and signatures; the most common choice for new zones, and what Instrument 1 uses |
| ED25519 | 15 | Recommended | Modern, fast, deterministic signatures |
| RSASHA256 | 8 | Recommended | The root zone's algorithm; large signatures |
| ECDSAP384SHA384, ED448 | 14, 16 | May | Validators are recommended to support them |
| RSASHA1, RSASHA1-NSEC3-SHA1 | 5, 7 | Must not | RFC 9904 listed them as not recommended; RFC 9905 raised that to must not. Resolver operators must treat them as unsupported, so zones still using them become insecure |
| RSAMD5, DSA | 1, 3, 6 | Must not | Retired |
For DS records, digest type 2 (SHA-256) is the one to publish; SHA-1 (type 1) must not be used for new DS records. NSEC3's own hash is still SHA-1, which is acceptable there because it only obscures names; it is not a signature.
Once names can be trusted, other things can hang off them. DANE (RFC 6698) publishes a hash of a server's TLS certificate or key in a signed TLSA record, at a name like _25._tcp.mail.example.test. A client that validates DNSSEC can then check a server's certificate against what the domain owner published, rather than (or as well as) trusting any of the hundreds of certificate authorities. It has found its main home in mail transport between servers; web browsers never adopted it.
Most of the work is done by your DNS host's signer, but the order of steps matters. Sign the zone first and check it with DNSViz while nothing points at the keys yet; at this stage a mistake costs nothing, because without a DS the zone is merely insecure. Then publish the DS at the registrar (or let CDS do it), and check again. Monitor signature expiration as you would a TLS certificate. Before any provider change, plan the DS.
NIST SP 800-81-2, the US government's guide to secure DNS deployment, covers the same lifecycle in more depth, including key storage and rollover scheduling.