Chapter 07 · Part II · Defending the network

DNS security

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.

65,536possible values of the 16-bit transaction ID, the only random number that once stood between a resolver and a forged answer
2005RFCs 4033, 4034 and 4035 published, defining DNSSEC as it is deployed today
2010the year the DNS root zone was signed, giving every validating resolver one key to start a chain of trust from

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?

The first answer wins

A race against the real answer

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.

P(spoof per window) = (R × W) / (N × P × I)
From RFC 5452, section 7.2, with one outstanding query. R × W is how many forged replies the attacker can land inside the window W; the bottom is the size of the haystack: N authoritative servers it might have asked, P source ports it might be using, and I = 65,536 transaction IDs. Make the bottom huge and the chance per try collapses.

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.

Go deeper: why the 2008 fix was urgent, and what still undoes it

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.

Instrument 1

The spoofing odds race

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.

Haystack size–
Guesses per window–
Chance per window–
Chance within a day–
Time to a 50% chance–
Last 1,000 races–

One lie, many victims

Cache poisoning and the TTL

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.

DefenseWhat it doesLimits
Random ID16 bits the forger must guess65,536 is far too few on its own
Random portAbout 16 more bits, per queryUndone by NAT or firewalls that make ports predictable
0x20 caseOne more bit per letter in the nameNeeds servers that echo case; short names gain little
Bailiwick ruleIgnores records outside the zone askedDoes not stop a forged answer to the question itself
TTL caps, flushLimits how long a lie can liveRecovery, not prevention
Spoof detectionWatches for floods of mismatched replies (RFC 5452 §9.3)Tells you an attack is happening, not that it failed
DNSSEC validationRejects any answer whose signature does not check outOnly 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.

Proof, not luck

DNSSEC: signatures all the way down

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.

  • DNSKEY holds a zone's public key. Each signed zone publishes its own.
  • RRSIG is a signature over an RRset: all the records of one type at one name, signed together. The A records for www.example.com get one RRSIG; the zone's DNSKEY set gets another. Every RRSIG carries an inception and an expiration time, so a signature is only valid during a window.
  • DS, delegation signer, lives in the parent zone. It holds a hash of the child's key. When com publishes a DS record for example.com and signs it, com is vouching for example.com's key.
  • NSEC and NSEC3 prove that something does not exist, so a forger cannot simply delete a record or pretend a zone is unsigned. More below.

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.

The DNSSEC chain of trust: the resolver's trust anchor matches the root key; the root signs a DS record for com, which matches com's key; com signs a DS for example.com, which matches example.com's key; that key signs the A record. Resolvertrust anchor:hash of root key root zone "."DNSKEY rootDS comRRSIG by root key comDNSKEY comDS example.comRRSIG by com key example.comDNSKEY examplewww A 192.0.2.80RRSIG by its key anchor matchesthe root key DS = hash ofthe child key Answerwww.example.com192.0.2.80secure ✓
Each zone signs its own data; each parent vouches for its child's key with a signed DS record. The resolver trusts one key and checks every link from there. The real chain uses two keys per zone, explained below, but the shape is the same.

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.

Go deeper: a worked DS check, and why zones have two keys

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:

DS digest = SHA-256( owner name | DNSKEY RDATA )
The parent stores only this 32-byte fingerprint. The resolver fetches the child's DNSKEY, hashes it the same way, and compares. A different key, even by one bit, gives a completely different digest.

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.

Go deeper: proving that something does not exist

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.

Instrument 2

Walk the DNSSEC chain

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.

–

Validation trace

    What the client gets–
    Extended DNS Error–
    Checks passed–

    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.

    Failure modes

    When DNSSEC makes a zone vanish

    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.

    • Expired signatures. RRSIGs have an expiration time, often a few weeks out. If the signing job stops, nothing breaks until the first signatures expire, and then the zone disappears for validators. Monitor the expiration of your zone's RRSIGs the way you monitor certificate expiry.
    • A key change without a DS change. Rolling the KSK means publishing the new key, waiting for caches, updating the DS at the parent, waiting again, and only then removing the old key. Skip a step and the DS points at a key that no longer signs. RFC 7583 sets out the timing for each method.
    • A DS left behind. Moving a domain to a DNS provider that does not sign, while the old DS stays at the registry, tells the world the zone should be signed when it is not. Remove the DS first, wait for its TTL, then move.
    • Stale trust anchors. A resolver that never learned the new root key would fail everything once the root rolls. Root rollovers are announced years ahead for this reason.

    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
    Signed is not secret

    Encrypted DNS and minimized questions

    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.

    Instrument 3 · who can read your question?
    Parties who read the full name–
    Parties who can alter the answer unseen–

    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.

    Go deeper: what encrypted DNS still leaves visible

    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.

    Around the protocol

    Protecting the names themselves

    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.

    • Lock the registration. Registrars offer locks against transfer and changes; many registries offer a stronger registry lock that requires an out-of-band, manually verified request before name servers or DS records can change.
    • Strong sign-in. Phishing-resistant multi-factor authentication on registrar and DNS-host accounts, with few people holding access (see Chapter 04).
    • Watch the delegation. Alert on any change to NS or DS records at the parent, and to the zone's own records, that did not come through your change process.
    • Watch certificates. An attacker who controls your DNS can get a certificate for your name. Certificate Transparency monitoring and CAA records, which name the certificate authorities allowed to issue for a domain, are covered in Chapter 03.

    Dangling records and subdomain takeover

    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.

    A dangling CNAME: shop.example.com still points at a cloud resource name that was deleted, so the name is free for someone else to claim. Your zoneshop.example.com CNAMEstore-4821.cloud.example.net stillpoints here Deleted resourcestore-4821name now unclaimed The fixdelete the recordbefore the resource Inventory every CNAME and its target; check that targets still exist;remove the DNS record first when you tear something down.
    The defense is bookkeeping: an inventory of records and what they point at, a teardown order that removes DNS first, and a regular sweep that flags records whose targets no longer exist.

    Protective DNS and DNS as a sensor

    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.

    Go deeper: where the neighbors pick up

    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.

    Side by side

    What each defense actually buys

    DefenseStops off-path forgeryStops on-path tamperingHides the questionProtects against account takeover
    Random ID + portMakes it very expensiveNoNoNo
    DNSSEC validationYes, for signed zonesYes, for signed zonesNoNo: the owner's account can change the DS
    DoT / DoHOn the device-to-resolver hopOn that hop onlyFrom the path, not the resolverNo
    QNAME minimizationNoNoFrom root and TLD serversNo
    Registry lock + MFANoNoNoYes, the main defense
    Record inventoryNoNoNoPrevents subdomain takeover
    Cheat sheet

    Terms from this chapter

    Transaction ID
    The 16-bit number a DNS query carries and its reply must echo; 65,536 possible values.
    Source port randomization
    Picking a fresh random UDP source port for every query, adding about 16 bits a forger must guess.
    Cache poisoning
    Getting a forged answer accepted into a resolver's cache, so it is served to every client until it expires.
    DNSSEC
    Extensions that sign DNS data so a validating resolver can prove an answer came from the zone's owner unaltered.
    RRSIG
    A DNSSEC signature over one RRset, valid between an inception and an expiration time.
    DS record
    A hash of a child zone's key, published and signed in the parent zone, that links the chain of trust.
    Trust anchor
    A key a validator trusts without proof, normally the root zone's key-signing key.
    Bogus
    DNSSEC verdict for data that should validate but fails; the resolver returns a server failure instead.
    DoT / DoH
    DNS carried inside TLS (RFC 7858, port 853) or inside HTTPS (RFC 8484), hiding lookups from the path.
    QNAME minimization
    A resolver sending each server only the part of the name it needs (RFC 9156).
    Subdomain takeover
    Someone else claiming the deleted resource a dangling DNS record still points to.
    Protective DNS
    A resolver that refuses to resolve known-malicious domains and logs lookups for detection.
    Where this comes from

    Sources