Almost every connection starts with a DNS lookup, and for most of the internet's history the answer was believed on sight: the first reply that matched a few numbers won. This chapter is about how forged answers get in, why a random port made forging thousands of times harder, how DNSSEC signs answers so a resolver can prove them, how encrypted DNS keeps the questions private, and the account, inventory and monitoring work that protects the names themselves.
Common mix-up: DNSSEC and encrypted DNS solve different problems. DNSSEC proves an answer is the one the zone's owner published, but sends it in the clear for anyone to read. DNS over TLS and DNS over HTTPS hide the question and answer on the way to your resolver, but prove nothing about whether the resolver's answer is genuine. A well-defended setup uses both.
Read first: DHCP & DNS on networks.jelia.nyc explains how a name becomes an address, what a recursive resolver, a stub and an authoritative server are, and how caching works. This chapter assumes all of that and asks a harder question: how does anyone know the answer is true?
Classic DNS runs over UDP, which has no handshake. A resolver sends one packet asking, say, for the address of www.example.com, and listens for one packet back. It cannot tell who actually sent the reply. All it can do is check that the reply fits the question it asked, and accept the first one that does.
RFC 5452, written to harden resolvers against exactly this, lists what a forged reply has to get right. It must answer the same question. It must carry the same 16-bit transaction ID the resolver picked. It must appear to come from the address of an authoritative server the resolver actually asked, and be sent to the address and UDP port the query came from. And it must arrive before the real answer does. The window between the query leaving and the real answer arriving is usually a few tens to a few hundreds of milliseconds.
An attacker on the path between resolver and server, who can see the query, needs no guessing at all; that is a different problem, and encryption and signatures are the answers to it. The interesting case is the off-path attacker who cannot see the query and has to guess. If the resolver always sent its queries from the same port, the only real secret was the transaction ID: 65,536 possibilities. A forger who can send a few hundred guesses inside each window has a chance of about one percent per try, and gets as many tries as it can provoke queries.
The fix that matters most is the P in that formula. If the resolver picks a fresh random source port for every query, from roughly 64,000 usable ones, the forger must guess the port and the ID together. The haystack grows by the same factor of about 64,000, from 65,536 to about four billion. CERT's 2008 vulnerability note on DNS cache poisoning (VU#800113) put it plainly: per-query source port randomization adds roughly 16 bits of randomness an attacker must guess, and vendors shipped patches to do exactly that.
There is one more trick that some resolvers use, called 0x20 encoding, after the bit in ASCII that separates upper and lower case letters. The resolver randomly mixes the case of the name it asks about, like wWw.ExAMpLe.cOm, and checks that the reply echoes the same pattern. Each letter adds one bit to guess. It only works when the authoritative server copies the question back exactly, which most do, and it adds little for names with few letters.
The formula has another lever: how many tries the attacker gets. In the simple model, each try needs the resolver to ask a fresh question, and a cached answer will not be asked again until its TTL runs out. That would limit an attacker to one try per TTL per name. RFC 5452 section 8.1 notes that there are techniques to make the resolver ask an effectively unlimited series of related questions, so the effective TTL drops to zero. Its own arithmetic: at 7,000 forged packets per second, a resolver using one source port can be spoofed with 50 percent probability within about 7 seconds; with 64,000 ports, the same rate needs around 116 hours.
That is why the 2008 coordinated patch was treated as an emergency, and why port randomization is a must, not a nice-to-have. The same CERT note warns about the thing that quietly undoes it: a firewall or NAT gateway that rewrites source ports to a predictable sequence. If your resolver sits behind port address translation (see NAT on networks.jelia.nyc), check that the ports leaving the building are still random. A resolver that randomizes perfectly behind a NAT that counts up from 1024 is back to 16 bits.
This calculator runs RFC 5452's arithmetic on the numbers you choose, then plays out races. Each race is simulated fairly: the resolver's secret ID, port and server are drawn at random, the forger fires its guesses in a random order, and it wins only if the right combination lands before the real answer. Nothing here touches a network; it is arithmetic and dice. Try the default first, then switch on port randomization and watch the red cells disappear.
A recursive resolver serves thousands of clients from one cache. That is what makes it fast, and what makes a forged answer so damaging: if one forgery is accepted, it is stored and handed to every client who asks, without another trip to the authoritative server. This is cache poisoning. One successful race against one resolver can send a whole office, campus or provider's customers to the wrong address.
The record's time to live (TTL) cuts both ways. A long TTL means fewer cache misses, so fewer windows for a forger to race in; RFC 5452 notes that if nothing else changes, only raising the TTL offers protection. But a poisoned record with a long TTL also stays poisoned longer, and an attacker who wins gets to choose the TTL of the lie. Resolvers cap how long they will keep any record for this reason, and operators can flush a cache once they spot a bad entry.
Resolvers also refuse to believe more than they asked. A reply about www.example.com can carry extra records in its additional section, and early resolvers would cache anything they were handed. Modern ones apply the rule RFC 5452 section 6 calls accepting only in-domain records, often called the bailiwick rule: a server asked about example.com is only believed about names inside the zone it was asked about, so an answer cannot smuggle in an address for an unrelated bank.
| Defense | What it does | Limits |
|---|---|---|
| Random ID | 16 bits the forger must guess | 65,536 is far too few on its own |
| Random port | About 16 more bits, per query | Undone by NAT or firewalls that make ports predictable |
| 0x20 case | One more bit per letter in the name | Needs servers that echo case; short names gain little |
| Bailiwick rule | Ignores records outside the zone asked | Does not stop a forged answer to the question itself |
| TTL caps, flush | Limits how long a lie can live | Recovery, not prevention |
| Spoof detection | Watches for floods of mismatched replies (RFC 5452 §9.3) | Tells you an attack is happening, not that it failed |
| DNSSEC validation | Rejects any answer whose signature does not check out | Only for signed zones; needs careful operation |
Every defense above the last row works by making guesses expensive. None of them lets a resolver tell a true answer from a lucky forgery. That needs a signature.
DNSSEC, defined in RFCs 4033 to 4035, adds digital signatures to DNS data. It does not change how questions are asked; it adds records that let a resolver check the answers. Four new record types do the work.
The result is a chain of trust. A validating resolver is configured with one key it trusts without proof, the trust anchor: the root zone's key-signing key. The root signs a DS record for com. That DS matches com's DNSKEY. com's key signs a DS for example.com, which matches example.com's DNSKEY, and that key signs the A record for www.example.com. If every link checks out, the answer is secure. The forger in Instrument 1 might still win the race, but its answer will not carry a valid signature, because making one needs example.com's private key, which never leaves the zone's signer.
A validating resolver gives every answer one of four verdicts, defined in RFC 4033 section 5. Secure: an unbroken chain of valid signatures from a trust anchor. Insecure: the resolver has signed proof that the chain deliberately stops, because some zone on the way is not signed; the answer is used, but unprotected. Bogus: the chain should be there but something fails, such as a bad or expired signature or a key that does not match its DS; the resolver refuses to answer and returns a server failure. Indeterminate: the resolver has no trust anchor covering the name at all.
The difference between insecure and bogus is the heart of the design. Removing signatures is not a way to slip a forgery past a validator, because the parent's signed records say whether a DS should exist. If com says, with a valid signature, that example.com has a DS, then an unsigned answer for example.com is bogus, not insecure.
RFC 4034 section 5.1.4 defines the DS digest as a hash over the child's owner name followed by its DNSKEY record data. With SHA-256, the digest type numbered 2, that is:
Most zones use two keys. A key-signing key (KSK) signs only the DNSKEY set, and its hash is what the parent's DS points at. A zone-signing key (ZSK) signs everything else. The split exists for operations: the ZSK can be changed often without involving the parent, while changing the KSK means updating the DS at the registry, which takes coordination. The root's KSK is the trust anchor built into resolvers, and changing it is a years-long public process. IANA's records show the root key generated in 2016, KSK-2017, signing the root from 2018-10-11 until 2026-10-11, when its successor KSK-2024 took over; resolvers needed the new trust anchor before that day to keep validating.
Instrument 2 simplifies to one key per zone so you can see each link, and it fakes the public-key signature with a hash, explained in its notes. The DS digest it computes is real SHA-256.
If a resolver asks for a name that does not exist, a forger would love to answer "no such name" and make a real site vanish. DNSSEC prevents this with authenticated denial of existence. An NSEC record says "the next name after this one in the zone is that one," and is signed like any other record. A name that falls between two neighbors provably does not exist.
The side effect is that anyone can walk the NSEC chain and list every name in the zone. NSEC3 (RFC 5155) uses hashed names instead, so the chain links hashes, which makes listing the zone harder though not impossible for guessable names. RFC 8198 lets validating resolvers reuse cached NSEC proofs to answer for whole ranges of non-existent names, which also blunts floods of random-name queries.
A small, made-up DNS tree: the root, com, and example.com, which publishes www.example.com at 192.0.2.80. Each zone's records are real data, the DS digests are real SHA-256 hashes, and the validator below recomputes every check every time you change something. Edit the address as if a forger changed it in transit, move the validator's clock past a signature's expiry, or use the scenario buttons, and read exactly which link breaks. Then try the DS button in two scenarios. After a key roll it is the correct fix. In the forger scenario it shows why a hijacked registrar account defeats DNSSEC: whoever can change the DS decides which key the world trusts.
Simplification: in real DNSSEC a signature is made with a private key and checked with the public one (RSA, ECDSA or Ed25519). Here a signature is a SHA-256 hash of the key, the data and the validity dates, so the validator can recompute it. That keeps the chain's shape exact while staying a toy: in this model anyone holding the public key could forge a signature, which real public-key cryptography prevents. Dates are day numbers in a pretend calendar.
A validator that refuses bogus answers is doing its job. The uncomfortable part is that most bogus answers in practice are not attacks. They are operational mistakes by the zone's own operator, and the result looks the same to users: the name stops resolving for everyone behind a validating resolver, while it still works for everyone else. That split is a strong clue when you troubleshoot.
The common causes are few and predictable.
When a resolver refuses, RFC 8914's Extended DNS Errors can say why, in a code attached to the failure: 6 for DNSSEC Bogus, 7 for Signature Expired, 9 for DNSKEY Missing, 10 for RRSIGs Missing. A resolver that sends them turns "the site is down" into a specific, fixable cause.
Monitoring checklist for a signed zone (illustrative) - RRSIG expiration on the SOA and DNSKEY sets: alert at 7 days left - DS at the parent matches a DNSKEY the zone publishes: check hourly - NS and DS records at the registry: alert on any change you did not make - Validation from an outside validating resolver: alert on SERVFAIL
DNSSEC signs answers; it encrypts nothing. Classic DNS sends every question and answer in the clear over UDP port 53, so the Wi-Fi operator in a café, your internet provider and anyone else on the path can read every name you look up. Names are revealing: a clinic, a job board, a debt counselor.
Two standards wrap the conversation between your device and its resolver in TLS, the same encryption that protects web pages. DNS over TLS (DoT), RFC 7858, runs DNS inside a TLS connection on its own port, 853. DNS over HTTPS (DoH), RFC 8484, sends DNS messages as HTTPS requests, normally on port 443 alongside ordinary web traffic. Both hide the question from the path and stop on-path tampering on that hop, and both authenticate the resolver with a certificate (see Chapter 03).
The trade-offs are real. Encryption moves trust; it does not remove it. The resolver still sees every question, so you are choosing whom to trust with your browsing history. When applications send DoH straight to a large public resolver, many users' lookups concentrate at a few operators. And an organization that relies on its own resolvers for internal names, for filtering known-bad domains and for detection logs loses all three if devices quietly bypass them. The usual answer in a managed network is to run an encrypted resolver of its own and configure devices to use it, rather than to block encryption.
The resolver's own lookups leak too. Traditionally a resolver sent the full name, www.example.com, to the root, to the com servers and to example.com's servers. QNAME minimization, RFC 9156, has it send each server only what that server needs: the root is asked about com, the com servers about example.com, and only example.com's own servers see the full name. It is cheap privacy hygiene, and many resolvers now do it by default.
A lookup of the made-up name jobs.careers.example.com from a laptop on café Wi-Fi. The table works out, for each party on the path, what it can read with the options you pick. Notice that switching DNSSEC on changes nothing in the first readout: it protects the answer's truth, not the question's privacy.
Encrypting DNS hides the lookup, but the connection that follows still goes to an IP address, and on most TLS connections today the name of the site is also sent in the clear in the TLS handshake, in the Server Name Indication field. Encrypted Client Hello is the effort to close that gap. DNS privacy is one layer; it is worth having, but it is not invisibility.
The most effective DNS attacks often do not touch the protocol at all. If someone logs in to the account where a domain is registered and changes its name servers, every resolver on earth will faithfully follow the new delegation, and DNSSEC will not object if the attacker also replaces or removes the DS record through the same account. The same holds for whoever can edit the zone at the DNS hosting provider.
In January 2019, CISA's Emergency Directive 19-01, Mitigate DNS Infrastructure Tampering, ordered US federal agencies to do four things within ten business days: audit their public DNS records, change the passwords on every account that can change DNS, add multi-factor authentication to those accounts, and monitor Certificate Transparency logs for certificates issued for their domains that they had not requested. That list is a good baseline for anyone.
A subtler problem comes from records that outlive what they point to. A team creates shop.example.com as a CNAME, an alias, pointing at a cloud-hosted storefront or bucket with a provider-assigned name. Later the storefront is deleted, but nobody deletes the CNAME. The provider's name is now free, and if the provider lets anyone claim it, whoever claims it controls what shop.example.com serves, under your domain, with your cookies' scope and your users' trust. OWASP's testing guide calls this subdomain takeover.
Because nearly everything starts with a lookup, the resolver is a good place to defend from. A protective DNS resolver refuses to resolve names on threat-intelligence lists of known malware, phishing and command-and-control domains, so a click on a bad link or a beacon from an infected machine fails at the first step. CISA runs a protective DNS service for US federal agencies, and MITRE D3FEND catalogs the technique as DNS denylisting. RFC 8914 gives such resolvers codes, 15 Blocked and 17 Filtered, to say plainly why a name did not resolve.
The resolver's logs are also one of the best detection sources an organization has. MITRE ATT&CK lists DNS as an application-layer protocol that attackers use to carry command-and-control traffic (T1071.004); unusually long or random-looking names, a host suddenly asking for thousands of unique subdomains of one domain, or lookups for names registered yesterday are all worth a look. That only works if devices use the resolver you log, which is another reason to run encrypted DNS yourself rather than block it. Chapter 17 covers building detections on logs like these.
Several DNS topics live elsewhere on this site. A rogue DHCP server on the local network handing out a malicious resolver address is in Chapter 06. Open resolvers abused to amplify denial-of-service floods are in Chapter 09. The DNS records that authenticate email, SPF, DKIM and DMARC, are in Chapter 10. And the routing attacks that can redirect traffic to a DNS server's address in the first place are next, in Chapter 08; DNSSEC is one of the things that still protects you when routing fails.
| Defense | Stops off-path forgery | Stops on-path tampering | Hides the question | Protects against account takeover |
|---|---|---|---|---|
| Random ID + port | Makes it very expensive | No | No | No |
| DNSSEC validation | Yes, for signed zones | Yes, for signed zones | No | No: the owner's account can change the DS |
| DoT / DoH | On the device-to-resolver hop | On that hop only | From the path, not the resolver | No |
| QNAME minimization | No | No | From root and TLD servers | No |
| Registry lock + MFA | No | No | No | Yes, the main defense |
| Record inventory | No | No | No | Prevents subdomain takeover |