3. The architecture
DNS · 3. The architectureThree kinds of server, one protocol between them, and almost every DNS misunderstanding is a confusion about which one you are talking to.
┌──────────────┐ │ APPLICATION │ getaddrinfo("x.com") └──────┬───────┘ │ ┌──────▼───────┐ │ STUB RESOLVER│ in libc, or systemd- │ │ resolved, or the browser │ knows: one │ server's IP │ └──────┬───────┘ │ "resolve this for me" (RD=1) ┌──────▼─────────────────┐ │ RECURSIVE RESOLVER │ │ caches everything │ │ walks the tree │ └──┬────────┬────────┬───┘ │ │ │ "what do you know?" (RD=0) ┌──▼──┐ ┌──▼───┐ ┌──▼────────┐ │ROOT │ │ .com │ │example.com│ │ . │ │ │ │ │ └─────┘ └──────┘ └───────────┘ AUTHORITATIVE SERVERS each answers only about its own zoneThe stub resolver
Section titled “The stub resolver”It is deliberately stupid. It sends one question to a configured address and trusts the reply.
cat /etc/resolv.confresolvectl statusresolvectl query example.comgetent hosts example.comnscd -g 2>/dev/null | head /etc/resolv.conf nameserver 10.0.0.1 nameserver 1.1.1.1 search example.com internal.example.com options timeout:2 attempts:2 rotate ndots:1 edns0 single-request
nameserver up to 3 are used. they are tried IN ORDER, not load- balanced, unless `rotate`. search appended to names with fewer than `ndots` dots ndots default 1 timeout default 5 SECONDS. the single worst default here.ndots, and the Kubernetes tax
Section titled “ndots, and the Kubernetes tax” KUBERNETES SETS ndots:5
SO `dig api.example.com` INSIDE A POD TRIES, IN ORDER: api.example.com.default.svc.cluster.local api.example.com.svc.cluster.local api.example.com.cluster.local api.example.com.ec2.internal api.example.com. ← finally
FIVE WASTED ROUND TRIPS, EACH AN NXDOMAIN, FOR EVERY EXTERNAL LOOKUP.cat /etc/resolv.conf # inside a podThe fix is either a trailing dot on external names (api.example.com.), a per-pod dnsConfig with ndots: 2, or NodeLocal DNSCache. It is the single most common DNS performance problem in Kubernetes, and the symptom is tail latency rather than failure.
The recursive resolver
Section titled “The recursive resolver”This is where the work happens: it starts at the root, follows referrals, caches every answer, and returns one final result.
WHAT IT MAINTAINS a cache, keyed on (name, type, class), expiring by TTL a NEGATIVE cache for NXDOMAIN/NODATA a list of root server addresses (the "root hints" — or it just asks a root, and gets the real list) infrastructure data: which nameservers are fast, which are timing out DNSSEC validation state, if enabled RESOLVER SOFTWARE Unbound the standard choice for a validating recursive resolver BIND 9 does everything; the reference implementation Knot Resolver modern, modular, fast PowerDNS Recursor widely deployed at ISPs dnsmasq a forwarder with a cache, not a real recursor systemd- resolved a stub plus a cache; a forwarder, not a recursor CoreDNS plugin-based; Kubernetes' defaultThe distinction between a recursor and a forwarder matters. A recursor walks the tree itself. A forwarder passes the question to another resolver and caches the reply. dnsmasq and systemd-resolved are forwarders; configuring them as if they were recursors produces a system that works only as long as the upstream does.
unbound-control stats_noreset | grep -E 'total.num|cache'dig +trace example.com # watch a recursion happendig +norecurse @1.1.1.1 example.com # is it already cached there?dig +norecurse against a public resolver is a neat trick: if you get an answer with a TTL lower than the zone’s configured value, it was cached, and the remaining TTL tells you how long ago.
The authoritative server
Section titled “The authoritative server”It holds one or more zones and answers only about them. It never performs recursion, and it never caches anything, because it already has the truth.
WHAT AN ANSWER LOOKS LIKE the `aa` flag set (Authoritative Answer) the data, from its own zone file OR a REFERRAL, if the question is below a delegation OR NXDOMAIN, if the name does not exist in its zone OR REFUSED, if the zone is not one it serves AUTHORITATIVE SOFTWARE NSD minimal, fast, authoritative-only Knot DNS modern, fast, DNSSEC- native BIND 9 the reference; does both roles PowerDNS Authoritative database backends CoreDNS can be authoritative too Route 53 / NS1 / Cloudflare / Google Cloud DNS manageddig @ns1.example.com example.com SOA # expect aadig @ns1.example.com other.com SOA # expect REFUSEDnamed-checkzone example.com /etc/bind/db.example.comkdig +tls @1.1.1.1 example.comPrimary and secondary
Section titled “Primary and secondary” PRIMARY ("master") holds the editable zone. the SOA's serial number is incremented here.
SECONDARY ("slave") pulls the zone by AXFR/IXFR and serves identical answers. authoritative, but not editable.
BOTH ARE LISTED IN THE NS RECORDS, AND RESOLVERS DO NOT KNOW OR CARE WHICH IS WHICH.That last line is the point of the design: a zone’s NS set is a list of equally-good answer sources, and the replication mechanism between them is invisible to the rest of the world. Chapter 8 covers the transfer protocols.
The root servers are not thirteen machines
Section titled “The root servers are not thirteen machines” THERE ARE 13 ROOT SERVER NAMES a.root-servers.net … m.root-servers.net BECAUSE 13 NS RECORDS PLUS GLUE WAS THE MOST THAT FIT IN A 512-BYTE UDP PACKET IN 1993.
THERE ARE OVER 1,900 ACTUAL INSTANCES, run by 12 independent organisations, in hundreds of locations.
THEY SHARE ADDRESSES VIA ANYCAST.dig . NS +shortdig +nsid @k.root-servers.net . SOA # which instance answered?curl -s https://root-servers.org/ | head -1Anycast, in one diagram
Section titled “Anycast, in one diagram” THE SAME IP ADDRESS ANNOUNCED FROM MANY PLACES. BGP ROUTES EACH CLIENT TO THE NEAREST ONE.
you in Berlin ──┐ ├─▶ 193.0.14.129 (Frankfurt you in Tokyo ───┤ instance) └─▶ 193.0.14.129 (Tokyo instance)
SAME ADDRESS. DIFFERENT MACHINE. NO DNS TRICKERY INVOLVED — this is routing, not resolution.Anycast is how every serious DNS operator achieves both latency and DDoS resilience: an attack hits whichever instance is nearest the attacker, and the rest of the world is unaffected. It also explains why dig from two locations can show different NSID values for the same server name, and why “the root server is down” is almost never a meaningful statement.
The resolver as a policy point
Section titled “The resolver as a policy point”A recursive resolver sees every name every client looks up, before any connection is made, which makes it the cheapest control point in a network — and the most contested one.
WHAT RESOLVERS ARE USED FOR BEYOND RESOLVING
BLOCKING malware and phishing domains (Quad9, corporate filters, Pi-hole) FILTERING content policy, safe search LOGGING the single best signal for detecting compromise and exfiltration SPLIT-HORIZON internal names that do not exist publicly STEERING rewriting answers to point at a local cache or proxydig @9.9.9.9 +short malware-test.example # Quad9 blocksdig @1.1.1.3 +short adult-test.example # family resolverpihole -q doubleclick.netThe mechanism is the same in every case: the resolver returns NXDOMAIN, or an address it chose, instead of the real answer. That is also, precisely, what a cache-poisoning attack does — which is why DNSSEC validation and resolver-based filtering are in permanent tension, and why filtering resolvers must strip the AD flag or decline to validate.
Software, and picking one
Section titled “Software, and picking one” JUST CACHE FOR ONE HOST systemd-resolved — already installed dnsmasq — tiny, also does DHCP
A REAL RECURSIVE RESOLVER FOR A NETWORK Unbound — the default recommendation Knot Resolver — modular, scriptable BIND 9 — if you need its features
AUTHORITATIVE, SELF-HOSTED NSD or Knot DNS — fast, minimal, authoritative-only on purpose PowerDNS Authoritative — database backends, APIs BIND 9 — views, dynamic update
IN A CLUSTER CoreDNS — plugin chain, Kubernetes nativeThe split between authoritative-only and recursive-capable software is deliberate and worth respecting. NSD and Knot DNS cannot recurse at all, which means they cannot be turned into an open resolver by a configuration mistake — a meaningful security property, and the reason the root servers run software of exactly that kind.
Where each role fails differently
Section titled “Where each role fails differently” STUB MISCONFIGURED → one host cannot resolve anything. /etc/resolv.conf, search domains, ndots.
RECURSIVE RESOLVER DOWN → everyone using it is offline, and nothing is wrong with your domain.
RECURSIVE RESOLVER CACHE POISONED/STALE → some users get wrong answers. the hardest class to diagnose, because it is invisible from the authority.
AUTHORITATIVE SERVERS DOWN → your domain disappears for everyone whose cache expires. gradual, then total.
DELEGATION BROKEN AT THE REGISTRAR → total, immediate for new lookups, and you cannot fix it from your own nameservers.The asymmetry is worth internalising: problems on the resolver side affect some users and are invisible to you, while problems on the authoritative side affect all users and are visible to everyone. Which direction a report comes from narrows the cause enormously.
What to take from this chapter
Section titled “What to take from this chapter”- Three roles: a stub that trusts one configured server, a recursive resolver that walks the tree and caches, and an authoritative server that holds a zone and never recurses or caches.
/etc/resolv.conf’s defaulttimeout:5 attempts:2means a dead first nameserver costs ten seconds. This is the root of most “DNS is slow” investigations.ndots:5in Kubernetes makes every external lookup try five cluster-local suffixes first. Fix it with a trailing dot, a per-poddnsConfig, or NodeLocal DNSCache.- A recursor walks the tree; a forwarder asks someone else and caches.
dnsmasqandsystemd-resolvedare forwarders, and treating them as recursors builds a dependency you did not intend. - An authoritative answer carries the
aaflag. Its four possible outcomes are data, a referral,NXDOMAIN, orREFUSEDfor a zone it does not serve. - Primary and secondary are an implementation detail invisible to resolvers — the
NSset is just a list of equally authoritative sources. - There are 13 root server names because that is what fit in a 512-byte packet in 1993, and over 1,900 instances behind them via anycast.
- Anycast is routing, not resolution: the same IP announced from many places, with BGP choosing. It works for DNS precisely because queries are single-packet, stateless and idempotent.
- The failure asymmetry is diagnostic: resolver-side problems affect some users and are invisible to you; authority-side problems affect everyone and are visible to all.
Next: records — the types that matter, what each is actually for, and the ones that are routinely misused.