skip to content

Racing the Resolver

Cache poisoning is offered as the way to hijack a name, when the race against a random port and identifier is the costly route. Interviewers test whether you price it against buying the delegation.

on this pageshow

explore

questions

4

Why can't an off-path attacker just send a forged DNS reply to a recursive resolver?

level: juniorimportance: must knowfreq 64%

answer

  1. the attacker can see nothing
  2. the resolver is matching outstanding state
  3. address, port, ID, question
  4. case of the name may be echoed
  5. the real answer ends the race

basics

~20 s

The resolver only accepts a reply that matches its outstanding query: same server address and port, same ephemeral port it asked from, same 16-bit message ID, same question. And it must arrive before the genuine answer.

solid answer

~50 s

An off-path attacker sees none of the traffic, so every field of the reply has to be guessed. A recursive resolver keeps state for each query in flight and accepts a UDP response only if the source address and port match the authoritative server it actually asked, the destination port matches the ephemeral port it sent from, the 16-bit message ID matches, and the question section echoes the same name and type. Many resolvers additionally randomise the case of the queried name and require it echoed back byte for byte. Miss any one of those and the packet is silently dropped. It is also a race: once the genuine reply lands, that query is retired and answered, so a late forgery has no outstanding state to match. The attacker is therefore guessing roughly thirty-odd bits inside a single round-trip.

code

text · 12 lines
text
outstanding query  (resolver -> authoritative)
  src 203.0.113.10:51972 -> dst 198.51.100.53:53
  id=0x8f2a  QNAME="WwW.eXaMpLe.CoM"  QTYPE=A

forged reply       (off-path, spoofed source address)
  src 198.51.100.53:53 -> dst 203.0.113.10:51972
  id=0x8f2a  QNAME="www.example.com"  A 192.0.2.66     <- question mismatch, dropped

genuine reply
  src 198.51.100.53:53 -> dst 203.0.113.10:51972
  id=0x8f2a  QNAME="WwW.eXaMpLe.CoM"  A 198.51.100.77  <- accepted, query retired
...

go deeper

for a junior

Be ready to list what a resolver checks on an arriving UDP answer — source address and port, your own ephemeral port, the 16-bit message ID and the echoed question — and to say plainly that an off-path attacker must guess all of it.

for a middle

Explain why the attempt is bounded in time rather than open-ended: the genuine reply retires the outstanding query, so the forgery has a window of one round-trip and no second chance for that lookup.

for a senior

Show that the check is statistical, not authentication. Nothing in the reply proves the sender holds the zone, so the real discussion is about how many guesses the attacker needs and whether the entropy survives the path.

for a principal

Own the framing that per-packet guessing odds are only one route to being believed as the authority for a name, and that budget spent on resolver behaviour does not close the cheaper routes to the same objective.

## The situation "Off-path" means the attacker has no position on the network path between the resolver and the authoritative servers it queries. They cannot see the query leave, cannot read any of its fields, and cannot delay or drop the real answer. All they can do is send packets from anywhere on the internet with a forged source address, hoping one is mistaken for the answer the resolver is waiting for. That is a very different problem from sitting on the wire, and the difference is entirely made of guessing. ## What the resolver is actually matching When a recursive resolver needs a name it does not hold, it sends a UDP query and records what it is waiting for. An arriving datagram is only considered as the answer to that query if all of the following line up: - **Source IP address** equal to the authoritative server the resolver chose to ask. A zone usually publishes several nameservers, so the attacker must forge the source address of the *right* one, or spray all of them. - **Source port 53** on that server, and **destination port** equal to the ephemeral port the resolver used for this query. Modern resolvers pick that port at random per query; historically many used one fixed port for their whole lifetime, which is the change that made this attack hard. - **The 16-bit message ID** (often called the transaction ID) carried in the DNS header, chosen at random per query. Sixteen bits is 65,536 possibilities. - **The question section** — the same owner name, type and class the resolver asked about. The attacker generally knows this, because they chose the name they want to poison. A common extra is *case randomisation of the queried name*: the resolver sends the name with the case of each letter chosen at random and requires the echoed question to match exactly. Servers are supposed to copy the question verbatim, so a genuine answer passes and a forger who normalises the name to lowercase does not. It adds roughly one bit per letter, and only against servers that faithfully preserve case. Anything that fails these checks is dropped. There is no error, no negotiation, no second chance for that packet. ## Why it is a race and not a puzzle The window is not "until the attacker gives up". It is the interval between the resolver sending its query and the genuine answer coming back — typically tens to a couple of hundred milliseconds. When the real answer arrives and matches, the resolver takes it, retires the outstanding query and serves the result. A forged packet that arrives one second later matches nothing: there is no query in flight for it to answer. It does not overwrite anything, and it is not cached alongside the real record. This is the single most common misconception about the attack — that a later, louder forgery wins. It does not; it is simply late. Because the resolver now holds the genuine answer, the attacker also cannot immediately try again for that same name: the resolver will serve from its own copy rather than asking again, so a fresh race requires a fresh outbound query. ## What this contrasts with An attacker who *is* on the path has none of these problems. They read the ephemeral port and the message ID straight off the wire and copy them into a reply, and they can be faster than the real server because they are closer. Everything above is what remains once you take that position away. Confusing the two is the classic interview slip: describing an on-path interception while claiming to describe off-path spoofing. ## What the check does and does not buy The matching rules are not authentication. Nothing in a plain DNS response proves the answering server holds the zone; the resolver is only checking that the packet looks like a reply to a question it asked. The defence is entirely statistical — it makes a correct guess unlikely, not impossible — which is why the interesting version of this question is not "can it be forged" but "how many guesses does it cost, and is there something cheaper the attacker could buy instead".

  • A forged reply with the correct message ID arrives a second after the genuine answer. What happens to it?
    Nothing. The query is no longer outstanding, so there is no state for the packet to match and it is discarded. It does not replace the cached record and it is not stored alongside it. To try again the attacker needs the resolver to ask that question afresh, which it will not do while it still holds an answer.
  • Does the attacker have to guess the resolver's IP address as well?
    No. The resolver's address is the target and is generally knowable — a campus or ISP recursive resolver is reachable and often published. What the attacker cannot see is the per-query ephemeral source port and the 16-bit message ID. They may, however, have to guess which of the zone's several authoritative servers was asked, so that the forged source address is the right one.
  • Why does randomising the case of the queried name add anything?
    Because a compliant server copies the question section back verbatim, the resolver can send the name with random capitalisation and require an exact byte match on the echo. A forger who does not know the pattern must guess it — roughly a bit per letter. It only helps against servers that preserve case, so resolvers treat it as a bonus rather than a guarantee.

It is like posting a reply to a letter you never saw: you must guess the recipient's box number and the reference code printed on the original, and get there before the real reply does.

saying these in an interview costs you the question

  • Says only the transaction ID has to match
  • Assumes the attacker can read the query to learn the ID
  • Thinks a later forged reply overwrites the cached answer
  • Describes on-path interception while calling it off-path spoofing
  • Treats the matching rules as authentication of the answer

context

open as a page

How much entropy must an off-path DNS forger beat inside one query's lifetime?

level: middleimportance: should knowfreq 47%

basics

~10 s

Roughly 2^30 to 2^32: a 16-bit message ID times 14 to 16 bits of ephemeral-port randomisation, all inside one round-trip. A gigabit of forgeries buys odds near one in tens of thousands per race.

open as a page

Told that source-port randomisation makes DNS cache poisoning infeasible, how do you answer?

level: seniorimportance: should knowfreq 41%

basics

~20 s

Concede the arithmetic, reject the conclusion. The objective is to be believed as the authority for a name, and that is on sale far cheaper at the registrar, where changing the delegation beats no entropy.

open as a page

Your registrar account for every company domain sits with marketing — what do you require, and how do you win it?

level: principalimportance: nice to knowfreq 27%

basics

~10 s

Treat the registrar account as a root of trust: registry-level change locks on load-bearing domains, phishing-resistant sign-in, a company-controlled recovery address, two-person approval. Win it by buying marketing a fast approval path.

open as a page