25.0 What this chapter gives you#
- You will be able to explain why the internet needs a naming system at all, and what people did in the years before it existed.
- You will be able to draw the shape of the whole name space, and read
github.com as a path starting from a single dot.
- You will be able to name the four kinds of thing that take part in a lookup, and say exactly which one does the running around.
- You will be able to walk through a real lookup of
github.com from the reader’s own machine, step by step, with realistic times for each step.
- You will be able to explain the thirteen root servers honestly, including why there are only thirteen names and why there are over 1,900 machines.
- You will be able to read every common record type and know when each is used, including the rule that catches people out at the top of a domain.
- You will be able to explain caching and TTL well enough to plan a migration, and to say why “waiting for DNS to propagate” is the wrong picture.
- You will be able to explain why the same name gives different answers in different countries, and separate the DNS reasons from the routing reasons.
- You will be able to say exactly why the reader’s
github.com resolved to 20.207.73.82, and prove the ownership of that address yourself.
- You will be able to diagnose a DNS fault with
dig, and tell in one command whether a problem is DNS at all or something else entirely.
25.1 The problem DNS solves#
PLAIN25.1.1 in simple words#
- Computers on a network find each other by number, not by name.
- The number for the reader’s copy of
github.com was 20.207.73.82.
- People are bad at remembering numbers and good at remembering names.
- So we need something that turns a name into a number, on demand, in a few thousandths of a second, billions of times a day, all over the world.
- That something is the Domain Name System, almost always called DNS.
- DNS is a lookup service. You give it a name. It gives you back a number.
- It is not a directory you browse. There is no list of every name. You can only ask about a name you already know.
- DNS does one small job, and does it for the entire internet. Almost nothing else on the internet works if DNS stops working.
- That is why a DNS fault feels like “the internet is down” even when every cable and every router is perfectly fine.
PLAIN25.1.2 a picture in your head#
- Think of a very large office building with no signs on any door.
- Every room has a number. Room 20207 on floor 73. Nothing else.
- You want to visit a person, not a number. You know the person’s name.
- At the entrance there is a desk. You say a name. The desk says a room number. You walk to that room.
- The desk does not walk you there. It only tells you where to go. Walking is still your job.
- Now imagine the building is the size of a planet, with billions of rooms, and rooms move house every few minutes.
- One desk could never hold all of that. So the building has one small desk per department, and the front desk knows which department desk to ask.
- That chain of desks, each knowing only its own part, is the shape of DNS.
Where this comparison breaks: a receptionist knows the answer or does not. A DNS server usually knows only who to ask next, and that is the whole trick. The front desk in DNS almost never holds the final answer. Also, in a real building you ask one desk once. In DNS the answer is remembered by everyone along the way for a set number of seconds, which changes the behaviour completely.
PLAIN25.1.3 a worked example#
- Before DNS existed, there was one file. It was called
HOSTS.TXT.
- It was a plain text file. Each line held one address and one name.
- Here is roughly what a line looked like in the ARPANET era.
HOST : 10.0.0.51 : SRI-NIC,NIC : DEC-2060 : TOPS20 : TCP/TELNET
HOST : 10.1.0.11 : UCLA-CCN : IBM-3033 : OS/MVS : TCP
HOST : 26.0.0.73 : SRI-KL,SRI : FOONLY-F2 : TENEX : TCP/FTP
- One organization maintained that file for everyone: the Network Information Center at Stanford Research Institute, in California.
- If your machine changed address, you emailed or phoned the Network Information Center. A human edited the file.
- Every other machine on the network downloaded the whole file, by FTP, every so often, and used its own copy.
- Work out the cost. If there are 300 machines and each downloads the file twice a week, that is 600 transfers a week from one server.
- Now double the number of machines. The file gets twice as big and twice as many machines download it. The load grows with the square.
- Worse: your copy is stale from the moment you download it. A machine that moved on Tuesday is unreachable for you until you download again.
- And there could be only one machine called
SRI-KL in the world, because the file had one flat list of names with no structure.
PLAIN25.1.4 what is really happening inside#
- The
HOSTS.TXT design failed for four separate reasons, and it is worth keeping them apart because DNS fixes each one differently.
- Load. One server served every machine. DNS fixes this by spreading the data across millions of servers, each holding a small piece.
- Freshness. A downloaded copy is a snapshot. DNS fixes this by asking at the moment you need the answer, and by attaching an expiry time.
- Naming clashes. One flat list means one name each. DNS fixes this by giving names a tree shape, so
www can exist under a million parents.
- Human bottleneck. One team edited every change. DNS fixes this by handing each organization control of its own branch. This is called delegation and it is the single most important idea in the system.
- Delegation means the top of the tree does not know your addresses. It only knows which servers to ask about your part of the tree.
- That keeps the top of the tree small, stable, and almost never changing, while the leaves change every minute.
TECHNICAL25.1.5 the engineer’s version#
HOSTS.TXT was maintained by the Network Information Center at Stanford Research Institute, known as SRI-NIC. Elizabeth Feinler ran that group and built and maintained the first ARPANET host directory.
- The file format and the FTP distribution procedure were written up in RFC 952 and RFC 953, both published in October 1985, which formalized a practice already years old.
- Paul Mockapetris, then at the Information Sciences Institute of the University of Southern California, designed DNS in 1983 at the request of Jon Postel.
- The original specification was published in November 1983 as two documents: RFC 882, “Domain Names - Concepts and Facilities”, and RFC 883, “Domain Names - Implementation and Specification”.
- Those were obsoleted in November 1987 by RFC 1034 and RFC 1035, with the same two titles. Those two documents are still the base specification today.
- Nearly forty years of later RFCs amend them. Nothing has replaced them.
- The first widely used implementation was BIND, the Berkeley Internet Name Domain, written at the University of California, Berkeley in 1984 and later maintained by the Internet Systems Consortium.
| HOSTS.TXT format |
Oct 1985 |
RFC 952 |
| DNS first spec |
Nov 1983 |
RFC 882, RFC 883 |
| DNS current base |
Nov 1987 |
RFC 1034, RFC 1035 |
| Negative caching |
Mar 1998 |
RFC 2308 |
| EDNS0 (current) |
Apr 2013 |
RFC 6891 |
- The honest version: RFC 1034 and RFC 1035 are not a clean read. Real behaviour today is spread over roughly one hundred RFCs, and the community maintains an informal list called “DNS Terminology”, RFC 9499, published in March 2024, purely to keep the vocabulary straight.
WORDS25.1.6 remember these#
- DNS — the thing that turns names into numbers — Domain Name System, the distributed hierarchical database defined by RFC 1034 and RFC 1035.
- Resolution — looking a name up — the process of mapping a domain name to resource records of a requested type and class.
- Delegation — handing control of a branch to someone else — NS records in a parent zone pointing at the authoritative servers of a child zone.
- HOSTS.TXT — the single hand-edited file everyone copied before DNS — the flat ARPANET host table distributed by FTP from SRI-NIC.
- Zone — one chunk of the tree that one operator controls — an administrative unit of the name space, bounded above and below by delegation points.
25.2 The shape of the name space#
PLAIN25.2.1 in simple words#
- Domain names look flat when you type them. They are not.
github.com is a path, and you read it right to left.
- At the far right, invisible, is the root. It is written as a single dot.
- Left of the root comes
com. That is a top level domain.
- Left of that comes
github. That is a second level domain.
- If there were more parts, like
api.github.com, each new part to the left is one step further down the tree.
- Each part between the dots is called a label.
- The full name, including the invisible dot at the end, is the fully qualified domain name, usually shortened to FQDN.
- Written properly it is
github.com. with a trailing dot. Nobody types that dot. Browsers and programs add it silently.
- The tree grows downwards from the root, which is why people call it an inverted tree. The root is at the top of the picture and the end of the name.
PLAIN25.2.2 a picture in your head#
- Think of a postal address, written the way most countries write it.
14 Baker Lane, Kothrud, Pune, Maharashtra, India.
- You read it inwards from the left, but the sorting machine reads it outwards from the right. Country first, then state, then city, then street.
- Nobody sorting post in Delhi needs to know every street in Pune. They need to know only “send this bag to Pune”.
- The Pune office needs to know only “send this to Kothrud”.
- Domain names are the same address, written in the machine’s order. The most general part is on the right, the most specific on the left.
com is the country. github is the city. api is the street.
Where this comparison breaks: a postal hierarchy is geographic and mostly fixed. The DNS tree is administrative, not geographic, and a branch can be handed to anyone anywhere. A .in name can be served from Texas, and a .com name can be served entirely from Mumbai. Also, post offices always exist at every level, whereas in DNS a level can be a pure label with no server at all.
PLAIN25.2.3 a worked example#
- Take the reader’s own name,
github.com, and split it into a path.
Written: github.com
Fully qualified: github.com.
Read right to left:
. <- the root, one empty label
com. <- top level domain
github.com. <- second level domain, delegated to GitHub
If we add a subdomain:
api.github.com. <- third level, GitHub's own choice
raw.github.com.
codeload.github.com.
- Note what is not in that picture.
www is not special. It is just a label somebody chose, the same as api or raw.
www.github.com is not “the website version” of github.com. It is a different name that happens to point at the same place.
- We can check that with one command, and here is the real answer.
$ dig +noall +answer www.github.com A
www.github.com. 3257 IN CNAME github.com.
github.com. 60 IN A 140.82.114.4
www.github.com is an alias pointing at github.com, which then has the address. Two names, one destination.
PLAIN25.2.4 what is really happening inside#
- Each label is stored separately, not as one long string.
- In a DNS message on the wire,
github.com is encoded as a length byte, then the letters, then a length byte, then the letters, then a zero.
06 67 69 74 68 75 62 03 63 6f 6d 00
6 g i t h u b 3 c o m end
- The final
00 is the root label. It has length zero. That is the trailing dot, and it is genuinely present in every message on the wire.
- So the trailing dot is not a typing convention. It is a real byte.
- A domain is a name and everything under it. A zone is the part of a domain that one server actually holds.
- Those two are different, and mixing them up causes real confusion.
com is a domain containing millions of names. The com zone contains almost none of their addresses, only pointers to who does.
- The point where a parent stops and a child starts is called a zone cut. At every zone cut there is a delegation.
TECHNICAL25.2.5 the engineer’s version#
- RFC 1035 section 2.3.4 sets the hard limits, and they have never changed.
| One label |
63 octets |
Length byte uses 6 bits |
| Full name on wire |
255 octets |
Includes length bytes |
| Labels per name |
127 max |
A consequence of the above |
| TTL field |
32 bits |
Signed use, max 2147483647 |
- Comparison of labels is case insensitive but case is preserved on the wire. RFC 4343, published January 2006, spells this out precisely.
- Many resolvers exploit that by randomizing the case of the query name and checking that the case comes back unchanged. This is called 0x20 encoding. It is a convention and a defence, not a standard.
- Top level domains come in categories: generic (gTLD) such as
com, country code (ccTLD) such as in, sponsored such as edu, and one infrastructure TLD, arpa, used for reverse lookups.
- The authoritative list is the IANA root zone database. As of version 2026081200, last updated 12 August 2026, it lists roughly 1,500 top level domains, including internationalized names that begin with
xn--.
- Certain names are reserved by standard and must never be delegated. RFC 2606, June 1999, reserves
example.com, example.net, example.org and the TLDs test, invalid, example and localhost.
- RFC 6761, February 2013, defines special use domain names that resolvers are expected to handle locally rather than by querying the tree.
- The honest version:
.local is not part of the global DNS at all. It is handled by Multicast DNS, RFC 6762, February 2013, which is a different protocol on UDP port 5353 that happens to reuse the DNS message format.
WORDS25.2.6 remember these#
- Label — one piece between the dots — an octet string of 1 to 63 octets, compared case insensitively.
- FQDN — the complete name including the final dot — a domain name terminated at the root, unambiguous with no search list applied.
- TLD — the last part, like
com — a zone delegated directly from the root zone by IANA.
- Zone — the part of the tree one operator serves — the set of records under a name, stopping at each delegation below it.
- Zone cut — the boundary between parent and child — the point where NS records in the parent delegate authority downward.
25.3 The four kinds of participant#
PLAIN25.3.1 in simple words#
- Four different things take part in a lookup. They are easy to confuse, and almost every DNS misunderstanding comes from confusing two of them.
- The stub resolver lives inside your own computer. It is small. It knows almost nothing. It asks one question and waits for one answer.
- The recursive resolver is a server somewhere else. It is the one that does the work. For the reader that server is at
1.1.1.1.
- The root servers sit at the very top. They know one thing: which servers handle each top level domain.
- The authoritative servers hold real answers for one zone each. The servers for
com are authoritative for com. GitHub’s servers are authoritative for github.com.
- Say this out loud, because it is the sentence people get wrong: your machine does not walk the tree. The recursive resolver walks the tree.
- Your machine asks one question, once, and waits. Everything else happens somewhere else, at somebody else’s expense.
PLAIN25.3.2 a picture in your head#
- Imagine you want a rare book and you are not going to leave your chair.
- You phone your local librarian and say: get me this book.
- That librarian does not have the book. But the librarian has a phone, a membership of the national library network, and patience.
- The librarian phones the national catalogue. The catalogue says: that subject belongs to the medical library.
- The librarian phones the medical library. That library says: that title is in the Pune branch.
- The librarian phones the Pune branch and gets the answer.
- Then the librarian phones you back with one sentence, and writes the answer on a card so the next person who asks gets it instantly.
- You made one phone call. The librarian made three. That is exactly the split between a stub resolver and a recursive resolver.
Where this comparison breaks: a librarian could read the book to you. A DNS resolver never fetches the page, only the address. It also never invents an answer, and never asks a server that is not named in a referral it just received. Also the librarian is trusted by you personally, whereas your resolver is often a company you have never had any dealings with.
PLAIN25.3.3 a worked example#
- Here is who holds what, for the reader’s actual lookup.
| Stub on the Mac |
Nothing, plus cache |
asks 1.1.1.1 |
| Recursive 1.1.1.1 |
Who to ask, plus cache |
walks the tree |
| Root server |
Where com lives |
13 names, A to M |
com servers |
Where github.com lives |
a to m gtld-servers |
| GitHub’s servers |
The actual address |
dns1.p08.nsone.net |
- Notice that only the bottom row knows the answer.
- Notice also that the top three rows never change from one lookup to the next. Only the bottom row is specific to
github.com.
- That is why a resolver that has been running for an hour answers most queries without leaving the building. It already knows the top three rows.
PLAIN25.3.4 what is really happening inside#
- The stub resolver on macOS is not a separate program you can see easily. It is library code plus a system service called
mDNSResponder.
- When an application calls
getaddrinfo, that call goes into the stub.
- The stub checks a small local cache. If the answer is there and not expired, it returns immediately, with no network traffic at all.
- If not, the stub builds one DNS query message and sends it to the configured resolver,
1.1.1.1, on UDP port 53.
- It sets a flag in that message called Recursion Desired. That flag means “please do all the work and come back with the final answer”.
- The recursive resolver honours that flag. Root, TLD and authoritative servers do not. They answer only from their own zone, or hand back a referral naming the next servers down.
- So the difference between a recursive resolver and an authoritative server is not the software. It is the role and the configuration.
- Many programs can do both. Running both roles on the same address is a known bad idea, because it mixes cached data with authoritative data.
TECHNICAL25.3.5 the engineer’s version#
- RFC 8499, obsoleted by RFC 9499 in March 2024, gives the precise terms: stub resolver, recursive resolver, iterative resolver, full resolver, authoritative server and forwarder.
- A forwarder is a fifth role that people forget. A home router usually runs a small forwarding resolver: it accepts your query, does no tree walking, and passes the query to an upstream recursive resolver.
- That is what the reader’s router at
192.168.0.1 would normally do. The reader has bypassed it by configuring 1.1.1.1 directly.
- The RD bit (Recursion Desired) is bit 8 of the DNS header flags. The RA bit (Recursion Available) is bit 15, set by a server that is willing to recurse for you.
- An authoritative server sets AA (Authoritative Answer). A cached answer from a recursive resolver does not have AA set. This is how you tell them apart in a packet capture.
- Query the flags directly with
dig. In the reader’s own output for github.com we see flags: qr rd ra, meaning it is a response, recursion was desired, recursion was available, and crucially there is no aa.
- QNAME minimization, RFC 9156, November 2021, changed what a recursive resolver sends upward. Instead of sending the full name to the root, a modern resolver sends only
com. to the root. Cloudflare and Google both do this by default now. This is a privacy improvement, deployed since 2019.
WORDS25.3.6 remember these#
- Stub resolver — the tiny piece in your own machine — the client-side code that sends one recursive query and does not follow referrals.
- Recursive resolver — the server that does the running around — a full service resolver that follows referrals and caches results.
- Authoritative server — a server that genuinely holds a zone — one that answers from zone data and sets the AA bit.
- Referral — “not me, ask them” — a response with no answer records and NS records for a child zone in the authority section.
- Forwarder — a middleman that just passes queries along — a resolver configured to send all queries to another recursive resolver.
- RD bit — “please do the work for me” — the Recursion Desired header flag, honoured only by recursive resolvers.
25.4 One full lookup, step by step#
PLAIN25.4.1 in simple words#
- We will now follow one real lookup all the way. The name is
github.com. The machine is the reader’s Mac, in India, on home broadband.
- The resolver is
1.1.1.1. The answer that came back was 20.207.73.82.
- Step 1. A program asks the operating system for the address of
github.com.
- Step 2. The stub resolver looks in its own small cache. Nothing there.
- Step 3. The stub sends one question to
1.1.1.1 and waits.
- Step 4.
1.1.1.1 looks in its own much bigger cache. Suppose it is cold and knows nothing, so it starts at the top.
- Step 5. It asks a root server: who handles
com?
- Step 6. The root server does not give an address. It gives a list of the
com servers. That is a referral.
- Step 7. It asks a
com server about github.com.
- Step 8. The
com server also gives a referral: GitHub’s own name servers.
- Step 9. It asks one of GitHub’s name servers about
github.com.
- Step 10. That server holds the zone, so it gives a real answer.
- Step 11.
1.1.1.1 stores the answer in its cache with a countdown.
- Step 12.
1.1.1.1 sends the answer back to the Mac.
- Step 13. The stub stores it too, and hands the address to the program.
PLAIN25.4.2 a picture in your head#
- Think of finding a person in a very large company on your first day.
- You ask reception. Reception says: that is the engineering building, ask their front desk.
- You go to engineering reception. They say: that is the platform team, ask their team lead.
- You go to the team lead. The team lead says: desk 42, second floor.
- Three questions, three answers, and only the last one was useful in itself.
- The first two were not failures. They were progress. Each one narrowed the search by a huge factor.
- Reception did not know about desk 42, and never will, and does not need to. That is the whole design.
Where this comparison breaks: you walked between buildings. In DNS the resolver sends fresh packets to fresh servers each time, and each hop is a completely independent question with its own timeout and its own retry. Also, reception in a real company will guess if unsure. A DNS server never guesses. If it does not have a delegation, it says so, and the resolver stops.
PLAIN25.4.3 a worked example#
- Here is the same lookup as a table, with the question asked at each step, what came back, and a realistic time on Indian home broadband.
| 1 |
stub cache |
miss |
0.1 ms |
| 2 |
1.1.1.1 |
(working) |
8 ms rtt |
| 3 |
root server |
referral to com |
18 ms |
| 4 |
com server |
referral to nsone |
25 ms |
| 5 |
nsone server |
20.207.73.82 |
30 ms |
| 6 |
back to Mac |
final answer |
8 ms |
- Cold total, nothing cached anywhere: roughly 90 milliseconds.
- Warm total, when
1.1.1.1 already has the answer: roughly 8 milliseconds, because only step 2 and step 6 happen.
- Warm total when the Mac itself has it cached: under 1 millisecond, with no packets sent at all.
- In real life the cold case is rare. The root and
com referrals live in a busy resolver’s cache for hours, so usually only the last hop is needed.
PLAIN25.4.4 what is really happening inside#
- Here is the same journey drawn out. Read downwards. Each arrow is one UDP packet in one direction.
stub 1.1.1.1 root .com github NS
| | | | |
| A? github | | | |
|------------>| | | |
| | NS? com. | | |
| |---------->| | |
| |<----------| | |
| | referral | | |
| | A? github.com | |
| |--------------------->| |
| |<---------------------| |
| | referral to nsone | |
| | A? github.com |
| |-------------------------------->|
| |<--------------------------------|
| | A 20.207.73.82 |
|<------------| | | |
| 20.207.73.82| | | |
v v v v v
- Count the packets. Eight in total for a completely cold lookup.
- Only two of them touch the reader’s own broadband line. The other six are sent by Cloudflare, from Cloudflare’s own network, at Cloudflare’s cost.
- That is the point of the design. The expensive work happens once, near the resolver, and is then reused for every other customer of that resolver.
- Each referral arrives with glue: the addresses of the servers named in the referral, in the additional section. Without glue the resolver would have to look up the name servers’ own names, which could loop forever.
- If a server does not reply within about 800 milliseconds, the resolver tries another server from the same list. There are always several.
TECHNICAL25.4.5 the engineer’s version#
- You can watch the whole chain with
dig +trace, which asks each level in turn from your own machine instead of asking a recursive resolver.
- The output starts with the root zone NS set, which
dig gets from its built-in hints file, then follows each referral.
$ dig +trace github.com
. 87203 IN NS a.root-servers.net.
. 87203 IN NS b.root-servers.net.
. 87203 IN NS c.root-servers.net.
...
;; Received 525 bytes from 198.41.0.4#53(a.root-servers.net)
com. 172800 IN NS a.gtld-servers.net.
com. 172800 IN NS b.gtld-servers.net.
...
;; Received 1174 bytes from 192.5.6.30#53(a.gtld-servers.net)
github.com. 172800 IN NS dns1.p08.nsone.net.
github.com. 172800 IN NS ns-421.awsdns-52.com.
...
;; Received 322 bytes from 192.31.80.30#53(d.gtld-servers.net)
github.com. 60 IN A 20.207.73.82
;; Received 55 bytes from 198.51.44.8#53(dns1.p08.nsone.net)
- The exact addresses in the final line depend on where you are. In India the reader got
20.207.73.82. From a machine in the United States the same command returns addresses in 140.82.112.0/20, which is GitHub’s own space. Section 25.10 explains that difference in full.
- The NS set for
github.com is genuinely split across two providers. This is real output, taken with dig, and it is worth studying.
$ dig +noall +answer github.com NS
github.com. 1348 IN NS dns1.p08.nsone.net.
github.com. 1348 IN NS dns2.p08.nsone.net.
github.com. 1348 IN NS dns3.p08.nsone.net.
github.com. 1348 IN NS dns4.p08.nsone.net.
github.com. 1348 IN NS ns-421.awsdns-52.com.
github.com. 1348 IN NS ns-520.awsdns-01.net.
github.com. 1348 IN NS ns-1283.awsdns-32.org.
github.com. 1348 IN NS ns-1707.awsdns-21.co.uk.
- Four servers at NS1, a managed DNS provider, and four at Amazon Route 53. Two independent providers, so an outage at either one does not take
github.com off the internet.
- Notice the Amazon servers are spread across
com, net, org and co.uk. That is deliberate: if one of those TLDs has trouble, the others still resolve. This is a convention among large operators, not a standard.
- Timing figures worth knowing, measured with
dig and reported in the Query time line at the bottom of every response:
| Local stub cache hit |
under 1 ms |
| Warm 1.1.1.1 in India |
4 to 15 ms |
| Cold, full tree walk |
60 to 150 ms |
| Server not responding |
800 ms then retry |
| Total giving up |
5 s default in dig |
WORDS25.4.6 remember these#
- Referral — “ask these servers instead” — a delegation response containing NS records for a child zone and no answer records.
- Glue record — the address of a name server, given along with its name — an A or AAAA record in the additional section, needed to break a dependency loop.
- Iterative query — asking one level at a time — a query with the RD bit clear, answered from local data or with a referral.
- Priming — how a resolver finds the root — a startup query for the root NS set, seeded from a built-in hints file.
- Query time — how long the answer took — the round trip measured by dig, printed in milliseconds at the foot of the response.
25.5 The root servers#
PLAIN25.5.1 in simple words#
- At the top of the tree sit the root servers. Every lookup that is not already cached starts there.
- There are thirteen of them, named with the letters A to M, at addresses ending in
root-servers.net.
- That is the sentence everyone repeats. It is true about the names, and very misleading about the machines.
- There are not thirteen machines. There are over 1,900 physical servers spread across the world, all answering on those same thirteen addresses.
- They are run by twelve different organizations, in different countries, under different legal systems, on purpose.
- No single organization can switch off the root. That was designed in.
- What the root knows is small. It knows which servers handle each top level domain, and nothing else. It has never heard of
github.com.
- The root zone file is only a few megabytes. You could email it.
PLAIN25.5.2 a picture in your head#
- Think of a telephone number that reaches whichever branch of a chain is nearest to you.
- You dial one number. Somebody answers. Which building they are sitting in depends entirely on where you are standing.
- In Pune it rings in Pune. In Frankfurt it rings in Frankfurt. Same number, different building, and you cannot tell which.
- That is what the thirteen root addresses are. Each one is a single number answered by hundreds of buildings.
- The trick that makes this work is called anycast, and we come back to it properly in section 25.9.
Where this comparison breaks: a phone chain routes calls by a central system that decides. Anycast has no central decision at all. Each network on the path picks the shortest route it knows to that address, so the choice emerges from the routing system rather than being made by anyone. There is also no failover list: if the nearest instance disappears, routing simply converges on the next nearest, usually within seconds, with no cooperation from anybody.
PLAIN25.5.3 a worked example#
- Here are the real thirteen, with their addresses and who runs them. This list has been almost unchanged for decades.
| a.root-servers.net |
198.41.0.4 |
Verisign |
| b.root-servers.net |
170.247.170.2 |
USC ISI |
| c.root-servers.net |
192.33.4.12 |
Cogent |
| d.root-servers.net |
199.7.91.13 |
Univ of Maryland |
| e.root-servers.net |
192.203.230.10 |
NASA Ames |
| f.root-servers.net |
192.5.5.241 |
ISC |
| g.root-servers.net |
192.112.36.4 |
US DoD NIC |
| h.root-servers.net |
198.97.190.53 |
US Army Research Lab |
| i.root-servers.net |
192.36.148.17 |
Netnod |
| j.root-servers.net |
192.58.128.30 |
Verisign |
| k.root-servers.net |
193.0.14.129 |
RIPE NCC |
| l.root-servers.net |
199.7.83.42 |
ICANN |
| m.root-servers.net |
202.12.27.33 |
WIDE Project |
- Verisign runs two, A and J. That is why thirteen names are run by twelve organizations.
- One address on that list changed recently, which is unusual enough to be worth remembering: B moved from
199.9.14.201 to 170.247.170.2 on 27 November 2023.
- Six of the thirteen are run by United States government or university bodies. Netnod is Swedish, RIPE NCC is Dutch, WIDE is Japanese. That mix is frequently argued about in internet governance, and it is fair to say the balance is historical rather than designed.
PLAIN25.5.4 what is really happening inside#
- Each of the thirteen addresses is announced into the global routing system from many separate locations at once.
- When your resolver sends a packet to
198.41.0.4, the routing system delivers it to whichever announcement is closest in routing terms.
- “Closest” here does not mean closest in kilometres. It means fewest network hops by the rules the routing protocol uses.
- The resolver has no idea which instance answered. It sees one address.
- You can find out, though. There is a special query,
hostname.bind in the CH class, that many instances answer with their own site identifier.
$ dig @198.41.0.4 hostname.bind CH TXT +short
"nnn1.a.root-servers.org"
- Ask that from Mumbai and from London and you will get different strings back from the same address. That is anycast made visible.
- The root servers are astonishingly boring by design. They serve one small zone, read only, and change roughly twice a day when the root zone is republished.
TECHNICAL25.5.5 the engineer’s version#
- As of 13 August 2026 the root server system reported 2,003 operational instances across the thirteen letters. The figure is published live by the root server operators and grows most months.
- The distribution is very uneven. Verified counts from the same source on that date included F at 366 instances, E at 328, D at 231, I at 90, and at the other end B and G at 6 each.
- Why thirteen, and not fourteen or a hundred? The limit came from the original 512-octet maximum for a DNS message over UDP, set in RFC 1035.
- A priming response must carry the NS records for the root plus the A records giving their addresses. With DNS name compression, thirteen name servers plus thirteen glue addresses fit inside 512 octets. Fourteen did not.
- That is why every root server is a single letter followed by
.root-servers.net: the shared suffix compresses to two bytes per record.
- The constraint is long gone. EDNS0, RFC 6891, lets a response be much larger, and the current priming response with IPv6 glue is well over 800 octets. The number thirteen survives purely because changing it has no benefit.
- The root zone has been signed with DNSSEC since 15 July 2010. The key signing key was rolled for the first time on 11 October 2018, an operation planned for years and completed without visible breakage.
- The root zone itself is generated by IANA, which is a function operated by Public Technical Identifiers under ICANN, and published by Verisign as the root zone maintainer.
| Letters |
13, A to M |
since 1980s |
| Operators |
12 organizations |
current |
| Instances |
2,003 |
13 Aug 2026 |
| Root zone signed |
yes |
15 Jul 2010 |
| TLDs delegated |
about 1,500 |
Aug 2026 |
- The honest version: people say “the root servers are the most attacked machines on the internet”. Attacks do happen, and there were notable events in October 2002 and February 2007, but the system has never gone down as a whole, and anycast means an attack is absorbed locally by the instances near the attacker rather than concentrated on one box.
WORDS25.5.6 remember these#
- Root server — the server at the top of the name tree — an authoritative server for the root zone, reachable at one of thirteen well known addresses.
- Anycast — one address answered from many places — the same prefix announced from multiple locations, with routing selecting the nearest.
- Hints file — the built-in list of root addresses — the bootstrap file used for priming before any DNS query can be made.
- Priming query — a resolver’s first question at startup — a query for the root NS set, used to replace the hints with live data.
- Root zone maintainer — the party that publishes the root file — currently Verisign, working from the zone content authorized by IANA.
25.6 Record types#
PLAIN25.6.1 in simple words#
- DNS does not only store addresses. It stores several kinds of fact about a name, and each kind has a short code called a record type.
- When you ask a question you name both the name and the type. “What is the A record for
github.com” is a different question from “what is the MX record for github.com”, and both are normal.
- An A record holds an IPv4 address. That is the common one.
- An AAAA record holds an IPv6 address. Said out loud as “quad A”.
- A CNAME record says “this name is another name for that name”.
- An MX record says where to deliver email for this domain.
- A TXT record holds free text, used mostly to prove ownership.
- An NS record names a server that is authoritative for a zone.
- An SOA record holds the administrative settings for a zone.
- A PTR record maps an address back to a name.
- An SRV record says which host and port run a named service.
- A CAA record says which certificate authorities may issue certificates for this domain.
PLAIN25.6.2 a picture in your head#
- Think of a person’s entry in an old paper address book.
- There is a street address. That is the A record.
- There is a second address for their new flat abroad. That is AAAA.
- There is a line saying “see under her maiden name”. That is CNAME.
- There is a separate line saying “send post care of the office”. That is MX, because letters go somewhere different from where the person lives.
- There is a scribbled note in the margin proving the page is genuine. TXT.
- There is a line saying which secretary handles her diary. NS.
- There is a stamp on the page saying who maintains this book and how often it is reprinted. SOA.
- There is a reverse index at the back listing addresses and who lives there. PTR.
Where this comparison breaks: an address book is one document owned by one person. DNS records for one name can be split across different owners, and the reverse index at the back is maintained by an entirely different organization that may never have heard of the person. That mismatch is real and it is why reverse lookups so often disagree with forward ones.
PLAIN25.6.3 a worked example#
- Here are real records for
github.com, queried with dig. Every line below is genuine output, only trimmed for width.
$ dig +noall +answer github.com SOA
github.com. 3600 IN SOA dns1.p08.nsone.net.
hostmaster.nsone.net. 1656468023 43200 7200 1209600 3600
$ dig +noall +answer github.com MX
github.com. 130 IN MX 0
github-com.mail.protection.outlook.com.
$ dig +noall +answer github.com CAA
github.com. 3600 IN CAA 0 issue "letsencrypt.org"
github.com. 3600 IN CAA 0 issue "digicert.com"
github.com. 3600 IN CAA 0 issue "sectigo.com"
github.com. 3600 IN CAA 0 issuewild "digicert.com"
$ dig +noall +answer www.github.com A
www.github.com. 3257 IN CNAME github.com.
github.com. 60 IN A 140.82.114.4
- Read the MX line. Mail for
github.com goes to Microsoft’s Outlook mail protection service, not to GitHub’s own machines. The domain is GitHub’s; the mail path is Microsoft’s. That is a small clue about who owns what.
- Read the CAA lines. Only four named certificate authorities may issue for
github.com. Any other authority that follows the rules must refuse.
- Read the SOA line.
dns1.p08.nsone.net is the primary server, hostmaster.nsone.net is the contact address with the first dot standing in for an at sign, and the numbers are serial, refresh, retry, expire and minimum, in that order.
PLAIN25.6.4 what is really happening inside#
- Records with the same name, type and class are handled together as a set, called an RRset. You cannot have half a set. All of it is returned or none of it.
- A CNAME is special and slightly dangerous. It says “stop, restart the whole lookup using this other name”.
- Because a CNAME redirects everything, the standard forbids any other record existing alongside a CNAME at the same name.
- That rule creates the problem everyone hits eventually. At the very top of a domain, called the apex or the naked domain, an SOA record and NS records must exist. They are compulsory.
- So a CNAME can never be placed at
github.com itself. Only at names below it, like www.github.com.
- If you have ever tried to point
example.com at a hosting provider’s hostname and been told it is not allowed, that is exactly this rule.
- The workarounds are covered in the technical block below, and it matters that some of them are not standards.
TECHNICAL25.6.5 the engineer’s version#
- The main types, with their numeric codes and defining documents.
| A |
1 |
IPv4 address, RFC 1035 |
| NS |
2 |
Delegation, RFC 1035 |
| CNAME |
5 |
Alias, RFC 1035 |
| SOA |
6 |
Zone parameters, RFC 1035 |
| PTR |
12 |
Reverse mapping, RFC 1035 |
| MX |
15 |
Mail exchanger, RFC 1035 |
| TXT |
16 |
Free text, RFC 1035 |
| AAAA |
28 |
IPv6 address, RFC 3596 |
| SRV |
33 |
Service location, RFC 2782 |
| CAA |
257 |
CA authorization, RFC 8659 |
- The CNAME restriction is RFC 1034 section 3.6.2: if a CNAME is present at a node, no other data should be present. DNSSEC records are the only exception the later standards carved out.
- Workarounds for the apex problem, and their honest status:
- ALIAS or ANAME records: an implementation detail of particular providers such as NS1, DNSimple and Route 53. Not a standard. The provider resolves the target and serves an A record itself.
- CNAME flattening: Cloudflare’s name for the same trick, introduced in
- Also not a standard.
- The HTTPS and SVCB record types, RFC 9460, published November 2023. These are a real standard and are supported by Chrome, Safari and Firefox, but they solve service binding rather than being a general apex CNAME.
github.com has no AAAA record. This was checked in August 2026 and the answer was NODATA, meaning the name exists but has no record of that type. The response carries an SOA record in the authority section instead.
$ dig +noall +answer +authority github.com AAAA
github.com. 1081 IN SOA dns1.p08.nsone.net.
hostmaster.nsone.net. 1656468023 43200 7200 1209600 3600
- That single fact explains a line in the reader’s own diagnostics: their system reported
IPv6: (none). Even with working IPv6 at home, a connection to github.com over IPv6 is impossible, because no IPv6 address is published for it.
- NODATA and NXDOMAIN are different and get confused. NXDOMAIN means the name does not exist at all. NODATA means it exists but not with that type. Both return an SOA in the authority section, which is what sets the negative cache time.
- TXT records are the internet’s junk drawer.
github.com publishes more than twenty of them, most of them proofs of ownership for third party services.
"v=spf1 ip4:192.30.252.0/22 include:spf.protection.outlook.com ..."
"MS=ms44452932"
"google-site-verification=UTM-3akMgubp6tQtgEuAkYNYL..."
"apple-domain-verification=RyQhdzTl6Z6x8ZP4"
"docusign=087098e3-3d46-47b7-9b4e-8a23028154cd"
- Reverse DNS lives under two special zones:
in-addr.arpa for IPv4 and ip6.arpa for IPv6. The address is written backwards, label by label. 20.207.73.82 becomes 82.73.207.20.in-addr.arpa.
- Reverse DNS is delegated by whoever holds the address block, not by whoever holds the domain name. Those are different parties, so the two directions are free to disagree, and usually do.
- Here are three real reverse lookups that make the point better than any explanation.
$ dig +short -x 140.82.112.3
lb-140-82-112-3-iad.github.com.
$ dig +short -x 8.8.8.8
dns.google.
$ dig +short -x 20.207.73.82
(no answer at all)
- The first has a PTR that names GitHub and even encodes the site code
iad, which is the airport code for Washington Dulles. The second is tidy. The third, the reader’s own answer, has no PTR record whatsoever.
- That is normal and is not a fault. Large cloud edges frequently publish no reverse records for service addresses. Mail servers are the one place where a missing or mismatched PTR causes real trouble, because receiving mail systems check it.
WORDS25.6.6 remember these#
- RRset — all records of one type at one name — a resource record set, the atomic unit of DNS data and of DNSSEC signing.
- Apex — the very top of a domain — the zone origin, where SOA and NS records are mandatory and a CNAME is therefore forbidden.
- CNAME — an alias to another name — canonical name record, which restarts resolution at the target and excludes all other data at that node.
- NODATA — the name exists but not with that type — a NOERROR response with an empty answer section and an SOA in the authority section.
- NXDOMAIN — the name does not exist — response code 3, cached for the time given by the SOA minimum field.
- PTR — the record that maps an address to a name — a pointer record under
in-addr.arpa or ip6.arpa, controlled by the address holder.
25.7 Caching and TTL#
PLAIN25.7.1 in simple words#
- If every lookup walked the whole tree, the root servers would receive trillions of queries a day and the internet would stop.
- They do not, because of caching. Almost every answer is reused.
- Every DNS answer carries a number called the TTL, short for time to live. It is a count of seconds.
- The TTL means: you may keep this answer and reuse it for this many seconds. After that, throw it away and ask again.
- A resolver that just answered a question for one customer can answer the same question for a million more without doing any work.
- This is why a busy resolver like
1.1.1.1 answers most questions in a few milliseconds. The answer was already sitting there.
- Caching is not an optimization bolted on later. It is load bearing. DNS without caching does not work at internet scale at all.
PLAIN25.7.2 a picture in your head#
- Think of a carton of milk with a date printed on it.
- The date is a promise from the dairy: this is good until then.
- You are allowed to use it any time before the date without checking.
- After the date you must go and get fresh milk. You do not get to argue.
- Now the important part. If the dairy changes its recipe today, every carton already in every fridge still has the old recipe until its date passes.
- Nobody comes to your house and swaps it. There is no recall.
- That is exactly what happens when someone changes a DNS record. Old answers sit in caches everywhere until each one expires on its own schedule.
Where this comparison breaks: milk actually goes bad. A DNS answer past its TTL may still be perfectly correct. The TTL is a policy about how long you may assume, not a statement about when the fact changes. Also, a resolver is allowed to throw the answer away early, for example when it runs short of memory. So the TTL is a maximum, not a minimum.
PLAIN25.7.3 a worked example#
- You can watch a TTL count down with your own eyes. Ask the same question twice, a few seconds apart, through a caching resolver.
$ dig +noall +answer github.com A
github.com. 60 IN A 20.207.73.82
... wait 10 seconds ...
$ dig +noall +answer github.com A
github.com. 50 IN A 20.207.73.82
... wait 20 seconds ...
$ dig +noall +answer github.com A
github.com. 30 IN A 20.207.73.82
... wait 35 seconds ...
$ dig +noall +answer github.com A
github.com. 60 IN A 20.207.73.82
- Read it carefully. The number falls by exactly one per second.
- The resolver is not re-asking. It is subtracting the time it has held the record and reporting what is left.
- When it reaches zero, the entry is dropped. The next query goes back to GitHub’s name servers and comes back at the full 60 again.
github.com publishes a short TTL of 60 seconds. That is a deliberate choice. It lets GitHub move traffic quickly at the cost of more queries.
- Compare that with a TTL of 86400 seconds, one day, which is common for records that never move, such as MX records for a stable mail provider.
PLAIN25.7.4 what is really happening inside#
- There is not one cache. There are usually four or five, stacked.
Application (browser has its own cache)
|
Operating system stub cache (mDNSResponder on macOS)
|
Home router forwarder cache (often, on 192.168.0.1)
|
Recursive resolver cache (1.1.1.1)
|
Authoritative server (the truth)
- The reader has removed one of those layers by pointing the Mac straight at
1.1.1.1 instead of at the router at 192.168.0.1.
- Each layer counts down independently. A record can be expired at one layer and still fresh at the layer above it.
- Browsers make this worse. Chrome and Firefox keep their own DNS cache and have historically ignored short TTLs, holding entries for around 60 seconds regardless. That is an implementation detail and it changes between versions.
- There is also negative caching: the fact that a name does not exist is itself cached, so a typo does not generate a fresh tree walk every time.
- Negative caching uses a different number: the last field of the SOA record, called the minimum field, which was repurposed for exactly this.
- For
github.com that field is 3600, so a nonexistent name under github.com is remembered as nonexistent for up to an hour.
TECHNICAL25.7.5 the engineer’s version#
- TTL is a 32-bit field in every resource record. RFC 2181, July 1997, section 8, states it must be treated as an unsigned value between 0 and 2147483647, and that values with the top bit set must be treated as zero.
- Negative caching is specified in RFC 2308, March 1998. The negative cache time is the lesser of the SOA minimum field and the SOA record’s own TTL. Most implementations additionally cap it, commonly at 3 hours.
- Real TTL values, read from live output, showing how wide the spread is:
| github.com A |
60 s |
moves often |
| github.com NS |
1348 s |
of 172800 max |
| github.com SOA |
3600 s |
1 hour |
| github.com CAA |
3600 s |
1 hour |
| example.com A |
300 s |
5 minutes |
| root NS set |
87203 s |
of 518400 max |
- Notice that the NS and root values shown are partly counted down already. The
com delegation NS records are published with a TTL of 172800 seconds, which is 48 hours, and the root NS set with 518400 seconds, six days.
- Standard migration procedure, and this is genuinely what operations teams do, in this order:
- At least 48 hours before the move, lower the TTL on the record from its normal value to 60 or 300 seconds. Wait for the old, long TTL to expire everywhere. This waiting step is the part people skip.
- Perform the change. Because the TTL is now short, caches drop the old answer within a minute or five.
- Watch traffic drain from the old address. Keep the old address serving until it is quiet.
- Once stable, raise the TTL back up to reduce query load.
- The phrase “DNS propagation” is common and slightly wrong. Nothing is pushed anywhere. There is no distribution process to wait for.
- The honest version: an authoritative change is live the instant the zone is published. What you are waiting for is other people’s caches to expire. The correct mental model is expiry, not propagation. The practical consequence is the same waiting, but the fix is different: you cannot speed up propagation, but you can plan the TTL in advance.
- There is one real exception. A change to the NS records must also be made at the parent registry, and registries publish their zones on a schedule, commonly every few minutes for
com. That step genuinely is a publication delay rather than a cache expiry.
- Useful commands:
dig +noall +answer github.com A # see the TTL
dig +norecurse @1.1.1.1 github.com A # cache hit or not
watch -n1 'dig +short +noall +answer github.com A'
sudo dscacheutil -flushcache # macOS: clear stub cache
sudo killall -HUP mDNSResponder # macOS: restart resolver
- On macOS both of the last two lines are needed together. Flushing the directory service cache alone does not clear
mDNSResponder. This has been true since macOS 10.10 and remains the standard pair today.
WORDS25.7.6 remember these#
- TTL — how many seconds you may reuse an answer — a 32-bit unsigned field per record, counted down by each cache that holds it.
- Negative caching — remembering that a name does not exist — caching of NXDOMAIN and NODATA responses, bounded by the SOA minimum field, RFC 2308.
- Cache hit — an answer given without asking anyone — a response served from local cache, identifiable by a TTL below the published maximum.
- Propagation — the common but inaccurate word for waiting after a change — what is really happening is expiry of previously cached answers.
- Authoritative TTL — the full value the zone owner publishes — the value seen when querying the authoritative server directly, never counted down.
25.8 Why the reader’s machine uses 1.1.1.1#
PLAIN25.8.1 in simple words#
- Your computer has to be told which resolver to use. It cannot guess.
- Normally it is told automatically, by the router, at the moment it joins the network.
- The router hands out a small bundle of settings: your address, the gateway to use, and the resolver to use. That bundle is called DHCP.
- By default the router usually names itself as the resolver, at
192.168.0.1, and then quietly passes queries on to the internet provider.
- The reader’s Mac is not doing that. It is using
1.1.1.1 directly.
- That happens for one of a few reasons: somebody set it by hand in network settings, an application set it, a privacy or VPN tool set it, or the provider’s own resolver was slow or unreliable and it was changed.
- The reader’s session also showed several
utun interfaces on the Mac, which are the kind of virtual network interfaces that VPN and tunnel software create. Such software very often changes the resolver as well.
- That is a strong hint, but it is a hint, not proof. Only the machine’s own settings can prove which of those it was.
PLAIN25.8.2 a picture in your head#
- Think of moving to a new town and needing a doctor.
- When you register at the town hall, they give you a default doctor: the nearest surgery, chosen for you, no thought needed.
- Most people keep the default forever, and it is fine.
- Some people deliberately switch to a different practice: it opens earlier, or has better equipment, or they trust it more with their records.
- There is a real trade. The default surgery is round the corner. The one you chose might be three towns away.
- Also, the local surgery knows which local hospital to send you to. The distant one might send you to a hospital near itself instead of near you.
Where this comparison breaks: a doctor is a person with duties to you. A public resolver is a company with no contract with you at all, and its incentives may be quite different from yours. Also you can change resolver in four seconds and change back, whereas changing doctor is paperwork.
PLAIN25.8.3 a worked example#
- The three best known public resolvers, with real launch dates.
| 8.8.8.8 |
Google |
3 Dec 2009 |
| 9.9.9.9 |
Quad9 |
Nov 2017 |
| 1.1.1.1 |
Cloudflare, APNIC |
1 Apr 2018 |
- Cloudflare announced
1.1.1.1 on 1 April 2018, which several people initially assumed was a joke because of the date. It was not.
- The address is not Cloudflare’s own. It is held by APNIC, the regional internet registry for Asia and the Pacific, and operated jointly under a research agreement, because
1.1.1.1 had historically been so polluted with stray traffic that nobody could use it.
- Quad9 was announced in November 2017 by IBM Security, Packet Clearing House and the Global Cyber Alliance. It is now a Swiss foundation based in Zurich, and it blocks known malicious domains by default.
- Google Public DNS,
8.8.8.8, was announced on 3 December 2009 and by 2018 was handling over a trillion queries per day.
- Each also has a second address, so a single failure does not cut you off:
1.0.0.1, 8.8.4.4, and 149.112.112.112 respectively.
PLAIN25.8.4 what is really happening inside#
- When the Mac joins the home network it broadcasts a DHCP request.
- The router replies with a DHCP offer containing numbered options. Option 3 is the gateway. Option 6 is the list of resolvers.
- For the reader, option 3 gave
192.168.0.1, the router. Something then overrode option 6 with 1.1.1.1.
- macOS keeps a per-interface resolver list. A manually set value in the network settings for Wi-Fi wins over whatever DHCP offered.
- A VPN or tunnel client goes further and installs its own resolver settings, often scoped so that some names go one way and others another.
- Now the important consequence. Your resolver is the thing that talks to authoritative servers. Those servers see the resolver’s address, not yours.
- If your resolver is answering you from Mumbai, then a service that steers traffic by location sees a query from Mumbai, and answers as if you are in Mumbai. That is usually right and occasionally very wrong.
TECHNICAL25.8.5 the engineer’s version#
- The resolver list arrives as DHCP option 6, “Domain Name Server”, defined in RFC 2132, March 1997. IPv6 uses a different mechanism, RDNSS in router advertisements, RFC 8106, March 2017.
- On macOS, inspect what is actually in force with these commands. Note that
/etc/resolv.conf on macOS is generated and is not the real source of truth.
scutil --dns | grep -A2 'resolver #1'
networksetup -getdnsservers Wi-Fi
cat /etc/resolv.conf # generated, informational only
- Honest trade-offs of using a public resolver instead of the provider’s:
| Latency to resolver |
usually lower |
often similar |
| CDN steering quality |
usually better |
can be worse |
| Filtering by ISP |
common |
depends |
| Query logging |
ISP sees all |
operator sees all |
| Encrypted transport |
rare |
usually offered |
- The most misunderstood item in that table is CDN steering. Content delivery networks decide which server to give you based on where the query appears to come from, which is the resolver, not you.
- A provider’s resolver sits inside the provider’s network, and content networks have spent twenty years mapping providers’ resolvers to providers’ customers. It is a very good signal.
- A large public resolver breaks that signal unless something replaces it.
- The replacement is EDNS Client Subnet, defined in RFC 7871, published May 2016 as an Informational document. The resolver adds a truncated version of your address, typically the first 24 bits for IPv4, to the query it sends to the authoritative server.
- That is enough for the content network to place you approximately, and not enough to identify you individually.
- The honest version, and the RFC says this itself: EDNS Client Subnet is a privacy loss. The RFC recommends it be off by default and used only where the benefit is clear. Google Public DNS sends it to networks that ask. Cloudflare’s
1.1.1.1 deliberately does not send it, and instead relies on having its own points of presence very close to users.
- This is a genuine disagreement between two serious operators. Google’s position is that better steering helps users more than the privacy cost. Cloudflare’s position is that the privacy cost is not worth paying and that a dense anycast network makes it unnecessary. Both are defensible.
- For the reader in India this matters concretely. Cloudflare operates points of presence in several Indian cities, so
1.1.1.1 answers from inside India, and the location signal is roughly correct even without client subnet. In a country with fewer points of presence the result can be an answer pointing at a server on another continent.
WORDS25.8.6 remember these#
- DHCP option 6 — how your machine is told which resolver to use — the Domain Name Server option in a DHCP offer, RFC 2132.
- Public resolver — a resolver anyone may use — an open recursive resolver operated as a service, such as 1.1.1.1, 8.8.8.8 or 9.9.9.9.
- EDNS Client Subnet — sending a rough version of your address upstream — an EDNS0 option carrying a truncated client prefix, RFC 7871.
- CDN steering — choosing which server you are sent to — authoritative responses varied by the apparent location of the querying resolver.
- scutil — the macOS tool that shows the real resolver configuration — the system configuration utility, queried with
scutil --dns.
25.9 Why the same name gives different answers#
PLAIN25.9.1 in simple words#
- Ask for
github.com in India and you may get 20.207.73.82. Ask in the United States and you may get 140.82.112.3. Both are correct.
- There is no single true answer to a DNS question for a large service. There is only the best answer for the asker, right now.
- Four different mechanisms produce this, and they are constantly mixed up.
- Anycast does it at the routing layer. Everyone gets the same address, and the network delivers them to a different machine.
- Geographic steering does it at the DNS layer. Different people are given different addresses based on where they seem to be.
- Latency steering also does it at the DNS layer, but based on measured speed rather than on a map.
- Weighted answers do it at the DNS layer too, sending a chosen share of people to each of several addresses.
- The difference matters because you fix them in completely different places.
PLAIN25.9.2 a picture in your head#
- Two ways to run a chain of shops with one advertised phone number.
- Way one: print one number on every poster, and arrange with the phone company that calls are routed to the nearest branch automatically. Everyone dials the same digits. That is anycast.
- Way two: print a different number on the posters in each city. Everyone dials different digits, and each set of digits reaches one specific branch. That is geographic DNS steering.
- From the customer’s side the experience looks identical. From the operator’s side they are utterly different problems.
- With way one, moving a customer to a different branch means changing routing and everyone in a region shifts at once.
- With way two, moving a customer means changing what the directory says, and the change only reaches people whose cached answer has expired.
Where this comparison breaks: a phone company’s routing is a private arrangement with one provider. Anycast routing decisions are made independently by thousands of networks with no coordination, using their own preferences, so the operator cannot fully predict who lands where.
PLAIN25.9.3 a worked example#
- Here is the difference in one table, using real observed data.
| Anycast |
Routing |
Every network |
Yes |
| Geo steering |
DNS |
Authoritative server |
No |
| Latency steering |
DNS |
Authoritative server |
No |
| Weighted round robin |
DNS |
Authoritative server |
No |
1.1.1.1 is pure anycast. Everybody in the world is told the same four digits. The routing system decides which of Cloudflare’s locations answers.
github.com uses DNS steering. The reader in India was told 20.207.73.82. A machine in the United States was told 140.82.112.3 at the same time. Different digits, from the same question.
- Both were checked and both are real. This is not a fault or an inconsistency.
- To see it yourself, ask the authoritative server directly and compare with what a distant resolver returns.
$ dig +short @1.1.1.1 github.com A # answers near you
$ dig +short @8.8.8.8 github.com A # may answer differently
$ dig +short @dns1.p08.nsone.net github.com A
PLAIN25.9.4 what is really happening inside#
- With anycast, one address block is announced into the global routing system from many separate locations.
- Every router on the internet learns several routes to that block and keeps the one its own policy prefers.
- Your packet therefore arrives at whichever location the chain of routers between you and it happened to prefer. Nobody consulted a map.
- Anycast is invisible to DNS. The DNS answer never changes. Two people in different countries can compare notes and see the same address while talking to different machines.
- With geographic steering, the authoritative name server looks at the address of the resolver that asked, or at the client subnet if one was sent, decides which region that belongs to, and returns a different set of records.
- This happens before any connection is made. The steering decision is baked into the answer, and it stays baked in for the length of the TTL.
- That is why steered records almost always carry short TTLs.
github.com uses 60 seconds. A steering decision that stuck for a day would be useless.
- Latency steering is the same as geographic steering but the decision comes from continuous measurement rather than from a geography database. It reacts to real network conditions, including congestion.
- Weighted answers simply divide traffic by proportion, for example 90 percent to a new stack and 10 percent to the old one during a migration.
- Plain round robin, where a server returns several addresses and rotates the order, is the oldest and dumbest form. It still exists and it still works, but it balances queries, not load, and it has no idea if a server is down.
TECHNICAL25.9.5 the engineer’s version#
- Anycast operates at layer 3 using BGP, the Border Gateway Protocol. The same prefix is originated from multiple sites, usually with the same origin AS number.
- Failure behaviour is the key property. If a site withdraws its announcement, routers converge on the next best path, typically within seconds to a few tens of seconds, with no DNS change and no TTL to wait for.
- The classic objection to anycast is that TCP sessions break if routing changes mid-connection. In practice this is rare, because routes are stable for the seconds a typical connection lasts, and operators use techniques such as consistent hashing at the site to limit the damage.
- DNS-based steering is implemented by authoritative servers that vary answers per query. Common products and services doing this include NS1 Managed DNS, Amazon Route 53 with latency and geolocation routing policies, Akamai’s authoritative service, and Azure Traffic Manager.
github.com is served by NS1 and Route 53 in parallel, both of which support per-query steering, which is consistent with the two very different answers observed in India and in the United States.
- Route 53 alone offers simple, weighted, latency, failover, geolocation, geoproximity and multivalue answer policies. These are product features, an implementation detail, not standards.
- The two layers combine. Cloudflare uses anycast for
1.1.1.1 and also returns different answers to different customers for hosted names. Microsoft fronts services with anycast edge addresses and also steers by DNS.
- Diagnosing which one is in play, in order:
| Same IP everywhere, different rtt |
Anycast |
| Different IP per country |
DNS geo steering |
| IP changes every few minutes |
Latency or weighted |
| Several IPs, order rotates |
Round robin |
- The honest version: for a big service it is usually both at once, plus a load balancer inside the destination network doing a third kind of distribution that you cannot see from outside at all. Do not expect a clean single answer.
WORDS25.9.6 remember these#
- Anycast — one address served from many places — the same BGP prefix originated at multiple sites, with routing selecting the destination.
- GeoDNS — different answers by location — authoritative responses selected by the apparent geography of the querying resolver or client subnet.
- Latency steering — answers chosen by measured speed — a routing policy that returns the endpoint with the lowest observed round trip time.
- Weighted answer — a chosen share of traffic per address — a policy that returns records in proportions set by the operator.
- Round robin — rotating the order of several addresses — the original and simplest DNS load spreading, which balances queries rather than load.
25.10 The reader’s own answer decoded#
PLAIN25.10.1 in simple words#
- The reader asked for
github.com and got 20.207.73.82.
- The first surprise is that this address does not belong to GitHub.
- It belongs to Microsoft. That sounds wrong until you know one fact.
- Microsoft bought GitHub. The deal was announced on 4 June 2018 and completed on 26 October 2018, for 7.5 billion United States dollars, paid in Microsoft shares rather than cash.
- Since then, GitHub has been a Microsoft company, and a lot of GitHub’s traffic is carried and fronted by Microsoft’s own global network.
- So a Microsoft address answering for
github.com is not a mistake and not a hijack. It is the company’s own infrastructure.
- The second thing about this address is where it is. Everything points at India, and specifically at Pune.
- The reader is in India. So this is the nearby doorway into Microsoft’s network, which is exactly what should have been handed out.
- That makes the reader’s fault more interesting, not less. DNS did its job perfectly. The right nearby address was returned. What failed came later.
PLAIN25.10.2 a picture in your head#
- Imagine a well known bookshop chain that gets bought by a supermarket group.
- The sign over the door still says the bookshop’s name. Customers still call it the bookshop.
- But the delivery lorries now say the supermarket’s name, the warehouses are the supermarket’s warehouses, and the loading bay you are sent to is a supermarket depot.
- If you looked only at the lorry you would think you had the wrong shop.
- You do not. You have the same shop, reached through a bigger company’s logistics network.
- And the depot you are sent to is the one near your town, not the one near the head office.
Where this comparison breaks: a supermarket owns its lorries outright and you can read the name on the side. On the internet you cannot see ownership directly. You have to look it up in a registry, and the registry records who was assigned the address, which is not always who is using it today.
PLAIN25.10.3 a worked example#
- Here is how to check the ownership yourself. Two independent methods, and they should agree.
- Method one, the registry lookup. Ask the regional internet registry who was assigned this address.
whois 20.207.73.82
- The answer, checked in August 2026, contains these fields:
NetRange: 20.192.0.0 - 20.255.255.255
CIDR: 20.192.0.0/10
NetName: MSFT
OrgName: Microsoft Corporation
Country: US
RegDate: 2017-10-18
Parent: NET20 (NET-20-0-0-0-0)
- Method two, the routing lookup. Ask which network is actually announcing this address into the global routing system right now.
prefix: 20.192.0.0/10
origin: AS8075
holder: MICROSOFT-CORP-MSN-AS-BLOCK, Microsoft Corporation
- The two agree. The address is registered to Microsoft and is announced by Microsoft’s own autonomous system number, 8075.
- Now do the same for the answer a machine in the United States received for the same name, and see the contrast.
| 20.207.73.82 |
20.192.0.0/10 |
AS8075 Microsoft |
| 140.82.112.3 |
140.82.112.0/24 |
AS36459 GitHub |
- Same name, same moment, two different companies’ networks. That is section 25.9 in action, and it is the clearest possible demonstration of it.
PLAIN25.10.4 what is really happening inside#
- Let us be strict about what is proven and what is only suggested, because this is exactly where people overclaim.
- Proven. The address
20.207.73.82 falls inside 20.192.0.0/10, which the registry records as assigned to Microsoft Corporation, registered on 18 October 2017.
- Proven. That prefix is announced into the global routing system by AS8075, Microsoft’s autonomous system.
- Proven. Microsoft acquired GitHub, announced 4 June 2018 and closed 26 October 2018, for 7.5 billion dollars in stock.
- Proven from the reader’s own trace. Every router from hop 7 onwards had a hostname ending in
ntwk.msn.net, which is Microsoft’s backbone naming. The final visible hops were pnq20 and pnq21, Pune site codes.
- Strongly suggested. The address is an India-facing edge. A public geolocation database places it in Pune, and the reader’s own traceroute reached Microsoft routers in Pune. Two independent signals agree.
- Inferred, not proven. That this specific address belongs to a particular Microsoft edge product. It is consistent with a Microsoft edge front end serving GitHub, but the address publishes no reverse DNS record at all, so there is nothing naming the service.
- Not knowable from outside. Whether GitHub or Microsoft configured this steering, and which internal system chose it.
- Notice how much can be established with two lookups and a traceroute, and how carefully the last two lines have to be worded.
TECHNICAL25.10.5 the engineer’s version#
- Microsoft holds several very large IPv4 blocks under NetName
MSFT. Two of them, both registered on 18 October 2017, are:
| 20.0.0.0/11 |
20.0.0.0 - 20.31.255.255 |
2,097,152 |
| 20.192.0.0/10 |
20.192.0.0 - 20.255.255.255 |
4,194,304 |
- The honest version: people say “20.0.0.0/8 is Microsoft”. Large parts of it are, and both of the blocks above are, but the statement is loose. Check the specific prefix, not the first octet. The registry answer for the exact address is the only thing worth quoting.
- IP registry lookups are separate from domain name lookups. For domains, WHOIS was formally retired for generic top level domains on 28 January 2025 in favour of RDAP, the Registration Data Access Protocol. For IP addresses the regional registries still answer WHOIS and also serve RDAP.
- The RDAP equivalent of the lookup above is a plain HTTPS request to the registry’s RDAP endpoint for the address, which returns JSON with the same fields as structured data rather than free text.
- Reverse DNS on this address returns nothing:
$ dig +short -x 20.207.73.82
$
- Compare with GitHub’s own address space, which does publish reverse names and even encodes a site code:
$ dig +short -x 140.82.112.3
lb-140-82-112-3-iad.github.com.
lb for load balancer and iad for Washington Dulles. That naming is a convention, not a standard, but it is a widely used one and it is often the single most useful clue in a trace.
- Putting the whole picture together for the reader’s session:
Name asked: github.com
Answered by: 1.1.1.1 (Cloudflare, anycast, likely in India)
Answer given: 20.207.73.82
Registered to: Microsoft Corporation (20.192.0.0/10)
Announced by: AS8075 Microsoft
Path observed: ISP -> msn.net Delhi -> Mumbai -> Pune -> silence
Reverse DNS: none published
Conclusion: correct nearby Microsoft edge for GitHub
- The last line matters for the rest of the reader’s investigation. The name resolved, quickly, to a plausible and verifiable address near them. There was never a DNS fault. The failure was in reaching that address, which is a different layer and a different chapter.
WORDS25.10.6 remember these#
- AS number — the identifier of one network operator — an autonomous system number used in BGP, such as AS8075 for Microsoft.
- Prefix — a block of addresses written as a range — an address plus a mask length, such as 20.192.0.0/10.
- RIR — the body that hands out address blocks — a regional internet registry such as ARIN, RIPE NCC or APNIC.
- RDAP — the modern replacement for WHOIS — the Registration Data Access Protocol, returning JSON over HTTPS, mandatory for gTLDs since Jan 2025.
- Edge — the nearest point of a big network to you — a front end site that terminates connections close to users and carries traffic onward internally.
25.11 DNS on the wire#
PLAIN25.11.1 in simple words#
- A DNS query is a small message sent over the network, usually as a single packet, and usually answered by a single packet coming back.
- It goes to port 53. A port is a number that says which service on a machine the message is for.
- It normally uses UDP, which is the fast, simple way to send a packet: fire and forget, no connection, no guarantee.
- That choice is why DNS is quick. There is no handshake to set up and tear down for a question that fits in one packet.
- It also means nothing is confirmed. If the packet is lost, nobody is told. The asker simply waits, gives up, and asks again.
- If the answer is too big for one packet, the server sets a flag meaning “this was cut short”, and the asker tries again over TCP.
- TCP is the slower, careful way, with a connection and acknowledgements. Same port 53, different transport.
- Every query carries a random number so the asker can match the answer to the question. That number is where a lot of the trouble in section 25.12 begins.
PLAIN25.11.2 a picture in your head#
- Think of a postcard versus a registered letter.
- A postcard is cheap, quick, and you write the reference number of your enquiry on it so the reply can be matched up.
- Nobody signs for a postcard. If it is lost in the sorting office, you find out only by noticing that no reply came.
- That is UDP. Most DNS is postcards.
- A registered letter needs a signature, a receipt, and several exchanges before anything is even delivered. It is much slower and much more certain.
- That is TCP. DNS uses it only when the reply will not fit on a postcard, or when the whole conversation needs to be private.
Where this comparison breaks: a postcard can be read by anyone handling it, and so can a plain DNS query, which is a fair part of the comparison. But a postcard cannot be forged into your letterbox by a stranger who guessed your reference number, and a DNS answer very much can. That is the attack described in the next section.
PLAIN25.11.3 a worked example#
- A DNS message has a fixed 12-byte header followed by four sections.
+---------------------------------------+
| Header 12 bytes |
+---------------------------------------+
| Question what was asked |
+---------------------------------------+
| Answer the records asked |
+---------------------------------------+
| Authority who is in charge |
+---------------------------------------+
| Additional extras and glue |
+---------------------------------------+
- In a normal successful reply, the answer section has the records you wanted and the other two are often empty.
- In a referral, the answer section is empty, the authority section has the NS records of the next level down, and the additional section has their addresses as glue.
- In a negative reply, the answer section is empty and the authority section has an SOA record, which supplies the negative caching time.
- Here is a real reply with those parts labelled by
dig itself.
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 51021
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0,
;; ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;github.com. IN A
;; ANSWER SECTION:
github.com. 21 IN A 20.207.73.82
;; Query time: 4 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; MSG SIZE rcvd: 55
- Read the last line. The whole reply was 55 bytes. That is the normal size of DNS traffic, and it is why UDP suits it so well.
PLAIN25.11.4 what is really happening inside#
- The header is only 12 bytes and every bit of it earns its place.
0 15
+-------------------------------+
| Query ID | 16 bits, random
+-------------------------------+
|QR|Opcode|AA|TC|RD|RA|Z |RCODE | flags
+-------------------------------+
| QDCOUNT | questions
+-------------------------------+
| ANCOUNT | answers
+-------------------------------+
| NSCOUNT | authority records
+-------------------------------+
| ARCOUNT | additional records
+-------------------------------+
- Query ID is a random 16-bit number. The reply must carry the same one or it is discarded.
- QR says query or response. AA says the answer came from an authoritative server. TC says the reply was truncated.
- RD and RA are the recursion flags from section 25.3.
- RCODE is the result code: 0 for success, 2 for server failure, 3 for name does not exist, 5 for refused.
- Sixteen bits of query ID means 65,536 possible values. Hold that number. It is the whole story of the next section.
- The original limit on a UDP DNS message was 512 bytes of payload. Anything longer had to be truncated and retried over TCP.
- That limit was raised by adding a fake record to the additional section that carries options and announces a larger acceptable size. This is EDNS0, and the fake record is called an OPT record. You can see it in the output above, labelled
OPT PSEUDOSECTION.
TECHNICAL25.11.5 the engineer’s version#
- Port 53 for both UDP and TCP was assigned in RFC 1035. TCP is mandatory to support, not optional, and RFC 7766, March 2016, made that requirement explicit and encouraged persistent TCP connections.
- TCP is used in four situations: a truncated UDP reply, zone transfers (AXFR and IXFR), any reply the resolver knows will be large, and as the base for DNS over TLS.
- EDNS0 was introduced in RFC 2671, August 1999, and revised as RFC 6891, April 2013. The OPT pseudo-record advertises the largest UDP payload the sender will accept.
- Common advertised sizes and why they are argued about:
| 512 bytes |
Original RFC 1035 limit |
| 1232 bytes |
DNS Flag Day 2020 recommendation |
| 1400 bytes |
Common older default |
| 4096 bytes |
Old BIND default, causes fragments |
- The 1232 figure comes from the smallest IPv6 MTU of 1280 minus 48 bytes of IPv6 and UDP headers. It was recommended by the DNS Flag Day 2020 effort precisely because larger values cause IP fragmentation, and fragmented UDP is dropped by many firewalls and is itself a security problem.
- Response codes worth memorizing:
| 0 |
NOERROR |
Success, or NODATA |
| 1 |
FORMERR |
Malformed query |
| 2 |
SERVFAIL |
Server could not answer |
| 3 |
NXDOMAIN |
Name does not exist |
| 5 |
REFUSED |
Policy refusal |
- SERVFAIL is the one that misleads people. It very often means a DNSSEC validation failure, not a broken server.
- Name compression, RFC 1035 section 4.1.4, lets a name that has already appeared be replaced by a two-byte pointer. This is why thirteen root servers fit in 512 bytes and why message sizes are hard to predict.
- The design flaw, stated plainly: the only things binding a reply to a query are the 16-bit ID, the source and destination addresses, the ports, and the question section. In the original design the source port was often fixed. That left roughly 16 bits of entropy for an attacker to guess.
WORDS25.11.6 remember these#
- Port 53 — the number DNS listens on — the IANA assigned port for DNS over both UDP and TCP.
- Query ID — the number matching a reply to a question — a 16-bit field that must match, giving only 65,536 possibilities.
- TC bit — “this reply was cut short” — the truncation flag, telling the client to retry over TCP.
- EDNS0 — the extension that allows bigger replies and new options — an OPT pseudo-record in the additional section, RFC 6891.
- SERVFAIL — “I could not answer” — RCODE 2, most often caused by a DNSSEC validation failure rather than an unreachable server.
25.12 DNS security and privacy#
PLAIN25.12.1 in simple words#
- DNS was designed in 1983 for a network of a few hundred trusted machines. Nobody was expected to lie.
- So the original design has no signatures, no encryption, and no way to tell a genuine answer from a forged one.
- There are two separate problems, and mixing them up causes bad decisions.
- Problem one is integrity: is this answer true, or did someone forge it?
- Problem two is privacy: who else can see which names I am looking up?
- The fix for integrity is DNSSEC, which signs records cryptographically.
- The fix for privacy is encrypting the conversation between you and your resolver, using DNS over TLS or DNS over HTTPS.
- They are independent. You can have either, both, or neither. DNSSEC does not hide anything, and encryption does not prove anything is true.
- There is also a third topic which is not a bug at all: DNS is deliberately used to block things, by governments, by companies, and by security teams.
PLAIN25.12.2 a picture in your head#
- Think of asking a stranger in the street for directions.
- The integrity problem: how do you know they are not lying and sending you to a pickpocket? A signature you can check is the answer. That is DNSSEC.
- The privacy problem: everyone standing nearby heard you ask for the address of the bank. Whispering solves that. That is encrypted DNS.
- Notice that whispering to a liar does not help, and getting a signed note from an honest person shouted across the street does not hide anything.
- You need both to be safe on both counts, and they are separate purchases.
Where this comparison breaks: a stranger has no reputation and no infrastructure. Real resolvers are large operators with published policies and sometimes with audits. Also, whispering to one person means that one person now knows everything you asked, which is the real trade in encrypted DNS: you have narrowed the audience from many to one, but that one now sees all of it.
PLAIN25.12.3 a worked example#
- In 2008 Dan Kaminsky found a way to poison a resolver’s cache reliably.
- The idea, simplified: the attacker makes the resolver ask about a name that is certainly not cached, such as
aaa001.example.com.
- While the resolver waits, the attacker floods it with forged replies, guessing the 16-bit query ID.
- The forged reply says “I do not know that name, but here is the address of the name server for the whole of
example.com, and it is my machine”.
- If one guess lands before the real reply arrives, the resolver caches a poisoned delegation for the entire domain, not just one name.
- If a guess fails, the attacker simply tries again with
aaa002.example.com, and can keep trying thousands of times per second.
- Work the numbers. With 65,536 possible IDs and thousands of attempts per second, a successful poisoning takes seconds to minutes, not centuries.
- That is what made it serious. Earlier attacks needed luck. This one needed only patience.
PLAIN25.12.4 what is really happening inside#
- The fix deployed in 2008 was to randomize the source port as well as the ID.
- The source port is another 16-bit number, so the attacker now has to guess both. That is roughly 32 bits instead of 16.
- Two to the power of 32 is about 4.3 billion. The same attack that took minutes now takes an infeasibly long time on a normal network.
- Note that this is a mitigation, not a cure. It makes forgery expensive rather than impossible.
- The real cure is signing. With DNSSEC, each record set is signed by the zone owner’s private key, and the matching public key is vouched for by the parent zone, all the way to the root.
- The chain looks like this: the root signs a fingerprint of the key for
com, com signs a fingerprint of the key for github.com, and github.com signs its own records.
- If you trust the root’s key, which is published and widely distributed, you can check every link. A forged answer fails the check and is discarded.
- Encryption is a separate change entirely. It wraps the query in TLS so that the network between you and your resolver sees only that you contacted the resolver, not what you asked.
TECHNICAL25.12.5 the engineer’s version#
- The Kaminsky flaw is CVE-2008-1447. Vendors released a coordinated patch on 8 July 2008, the first large multi-vendor synchronized DNS patch. Details leaked on 21 July 2008, ahead of the intended embargo, and the full talk was given at Black Hat that August.
- Source port randomization was formalized in RFC 5452, January 2009, “Measures for Making DNS More Resilient against Forged Answers”. Daniel J. Bernstein’s djbdns and PowerDNS had already been doing it for years.
- DNSSEC core specifications are RFC 4033, RFC 4034 and RFC 4035, all published March 2005, replacing the earlier and unworkable RFC 2535 of 1999.
- The record types added are DNSKEY, RRSIG, DS, NSEC and NSEC3.
| DNSKEY |
The zone’s public key |
| RRSIG |
Signature over one RRset |
| DS |
Hash of a child’s key, in parent |
| NSEC |
Proof a name does not exist |
| NSEC3 |
Same, with hashed names |
- The root zone was signed on 15 July 2010. The key signing key was rolled for the first time on 11 October 2018.
- Adoption is genuinely patchy and it is dishonest to pretend otherwise. As of 2025, about 48 percent of country code TLDs operate DNSSEC, but second level adoption is roughly 4 percent in
com and 5 percent in net, while exceeding 50 percent in nl, cz, no, se and nu.
- You can see a real DS record for
com with dig:
$ dig +noall +answer com DS
com. 53825 IN DS 19718 13 2
8ACBB0CD28F41250A80A491389424D341522D946B0DA0C029...
- Experts disagree about DNSSEC. Supporters say it is the only real fix for forgery and enables things such as publishing certificate fingerprints in DNS. Critics say the complexity causes more outages than the attacks it prevents, that key management errors take whole domains offline, and that TLS already authenticates the destination. Both positions are held by serious engineers and both have evidence.
- Encrypted transports:
| DNS over TLS |
853 |
RFC 7858 |
May 2016 |
| DNS over HTTPS |
443 |
RFC 8484 |
Oct 2018 |
| Oblivious DoH |
443 |
RFC 9230 |
Jun 2022 |
- DNS over TLS is easy for a network operator to see and to block, because it uses a dedicated port. DNS over HTTPS hides among ordinary web traffic on port 443 and is therefore very hard to distinguish or block.
- That difference is the whole political argument. Firefox enabled DNS over HTTPS by default for United States users on 25 February 2020 and Chrome followed in May 2020, and network operators, schools and some governments objected loudly, because it removed their visibility and their filtering.
- Oblivious DNS over HTTPS, RFC 9230, June 2022, splits the knowledge: a proxy sees your address but not your query, and the resolver sees your query but not your address. It is deployed but not widespread.
- DNS-based filtering and blocking, stated neutrally, comes in three forms:
- Refusing to answer, returning NXDOMAIN or REFUSED for a blocked name. Used by Quad9 for malware, by corporate networks, and by regulators.
- Answering with a different address, sending users to a warning page.
- Sinkholing, where a known malicious name is deliberately pointed at a researcher’s machine so infected computers can be counted and contained.
- NXDOMAIN hijacking is when an internet provider replaces a nonexistent answer with an address of its own, usually showing search results and advertisements. The most famous case was Verisign’s Site Finder, which did this for the whole of
com and net from 15 September 2003 and was withdrawn on 4 October 2003 after heavy technical objection.
- It breaks things beyond the browser. Any software that relies on NXDOMAIN to detect a typo or to finish a search list is confused by a fake address.
- The most famous sinkhole is the WannaCry kill switch domain, registered on 12 May 2017 by the researcher Marcus Hutchins, which halted the spread of the ransomware because the malware checked whether that name resolved.
WORDS25.12.6 remember these#
- Cache poisoning — tricking a resolver into storing a false answer — off-path injection of forged responses matching a pending query.
- Kaminsky attack — the 2008 method that made poisoning practical — repeated forced lookups of random subdomains with forged in-bailiwick delegations.
- DNSSEC — cryptographic signatures on DNS records — a chain of trust from the root using DNSKEY, RRSIG and DS records, RFC 4033 to 4035.
- DoT and DoH — encrypting the query to your resolver — DNS over TLS on port 853 and DNS over HTTPS on port 443.
- Sinkholing — pointing a bad name at a controlled machine — deliberate redirection of malicious domains for containment and measurement.
- NXDOMAIN hijacking — replacing “no such name” with an advert page — an operator substituting a synthesized A record for a negative response.
25.13 Owning a name#
PLAIN25.13.1 in simple words#
- You cannot buy a domain name. You rent it, for a fixed period, from a chain of organizations.
- Three roles matter, and they are almost always confused.
- The registrant is you. The person or company the name is registered to.
- The registrar is the shop you buy from. It takes your money, holds your account, and passes your instructions upward.
- The registry runs the whole top level domain. There is exactly one registry per TLD. It holds the actual zone file.
- So when you register
example.com, you pay a registrar, and the registrar tells the com registry to add your name.
- Above all of that sits ICANN, which decides which top level domains exist and accredits registrars, and IANA, which maintains the root zone contents.
- Renting matters. If you stop paying, you lose the name, and someone else can take it. There is no ownership to fall back on.
PLAIN25.13.2 a picture in your head#
- Think of a market stall pitch in a covered market.
- The market authority owns the building and decides how many halls there are. That is ICANN.
- Each hall has one manager who keeps the master plan of every pitch in that hall. That is a registry.
- You do not talk to the hall manager. You go to one of several letting agents who have a contract with the hall. That is a registrar.
- You sign with the agent, pay yearly, and your name goes on the hall’s master plan. You are the registrant.
- If you stop paying, the pitch is cleared and relet. Your sign comes down and somebody else’s goes up, in the same spot, with your old customers still walking towards it.
Where this comparison breaks: a market stall is physical and somebody would notice a stranger standing in it. A domain can be transferred away silently by someone who gets into your account with the agent, and the first sign is your email and your website quietly arriving somewhere else.
PLAIN25.13.3 a worked example#
- Here is what actually happens when a name is registered, in order.
1. You choose example.com at a registrar.
2. Registrar checks availability with the com registry.
3. You pay, and give contact details.
4. Registrar creates the domain object at the registry,
using the EPP protocol, with your NS records attached.
5. Registry adds to the com zone:
example.com. 172800 IN NS ns1.yourhost.net.
example.com. 172800 IN NS ns2.yourhost.net.
6. Registry republishes the com zone (minutes, not days).
7. Your name servers now receive queries for the name.
8. You add A, MX and TXT records at your DNS host.
- Read step 5 again. The registry does not store your website address. It stores only the names of your name servers.
- That is the delegation. The
com zone contains hundreds of millions of NS records and almost no A records for customer domains.
- Step 8 is at a completely different company. Your DNS hosting can be at Cloudflare, Route 53 or NS1 while your registrar is somewhere else entirely.
github.com shows this split clearly: the delegation at com names servers at NS1 and at Amazon Route 53, neither of which is a registrar.
PLAIN25.13.4 what is really happening inside#
- There are two copies of your name server list, and they must agree.
- One is at the parent, in the
com zone, put there by your registrar. This is the one the world actually follows.
- The other is inside your own zone, as NS records at your apex. This one is what your own servers claim.
- If they disagree, resolvers follow the parent, and you get confusing half-working behaviour that is hard to debug. Check both when in doubt.
- When a name expires, it does not vanish that day. There is a sequence of grace periods, and it is worth knowing because it decides whether you can still get your name back.
- Roughly: the name stops working, then there is a period where you can renew normally, then a redemption period where you can recover it at a much higher fee, then a short pending-delete window, and then it is released.
- Domain hijacking usually has nothing to do with DNS itself. It is theft of the registrar account, or a fraudulent transfer request, or a compromised email address used for password resets.
TECHNICAL25.13.5 the engineer’s version#
- ICANN, the Internet Corporation for Assigned Names and Numbers, was formed on 30 September 1998 as a California non-profit corporation.
- The IANA functions, including maintaining the root zone, are performed by Public Technical Identifiers, an ICANN affiliate created when United States government stewardship ended on 1 October 2016.
- Registrars communicate with registries using EPP, the Extensible Provisioning Protocol, RFC 5730 to RFC 5734, published August 2009.
- Example registries:
| com, net |
Verisign |
Also root zone maintainer |
| org |
Public Interest Registry |
Non-profit |
| uk |
Nominet |
UK, since 1996 |
| in |
NIXI |
India |
- The standard gTLD lifecycle, as set by ICANN policy:
| Registered term |
1 to 10 years |
| Auto-renew grace |
0 to 45 days |
| Redemption grace |
30 days |
| Pending delete |
5 days |
| Add grace period |
5 days |
- The Add Grace Period allows a registrar to delete a new registration for a refund within five days. This was abused at enormous scale around 2007 in a practice called domain tasting, and ICANN largely ended it in 2009 by charging fees on excessive AGP deletions.
- WHOIS changed fundamentally in 2018. The GDPR took effect on 25 May 2018, and ICANN adopted a Temporary Specification in May 2018 requiring registrars to redact most registrant contact data from public WHOIS output.
- Before that, a WHOIS query returned a name, postal address, phone number and email for most domains. After it, most gTLD records show only the country, the state, and an anonymized contact form or relay address.
- WHOIS itself was formally sunset for generic top level domains on 28 January 2025, replaced by RDAP, which returns structured JSON over HTTPS and supports differentiated access for authorized parties.
- Protection against hijacking is layered, and the important controls are:
- EPP status codes such as
clientTransferProhibited and clientUpdateProhibited, set by the registrar on your instruction.
- Registry lock, a manual out-of-band process at the registry level, offered for high value names. Changes require human verification.
- Two-factor authentication on the registrar account, and a dedicated email address that is not hosted on the domain itself.
- Real cases worth knowing. On 15 January 2005 the New York provider
panix.com was transferred away without authorization and its mail and web traffic redirected for most of a day. On 27 August 2013 the Syrian Electronic Army altered DNS delegations for the New York Times and other sites through a compromised reseller of the registrar Melbourne IT.
- Both were registrar-level compromises. No DNS protocol weakness was involved in either. That is the pattern.
WORDS25.13.6 remember these#
- Registrant — the person or company a name is registered to — the legal holder of a domain registration for its term.
- Registrar — the shop you buy the name from — an ICANN-accredited entity that creates and manages domain objects at a registry.
- Registry — the operator of a whole top level domain — the sole operator of a TLD zone, such as Verisign for
com.
- EPP — the protocol registrars use to talk to registries — the Extensible Provisioning Protocol, RFC 5730 to 5734.
- Redemption grace period — the expensive last chance to get an expired name back — a 30-day ICANN-mandated recovery window before pending delete.
- Registry lock — the strongest anti-hijack control — a registry-level status requiring manual out-of-band authorization for any change.
25.14 Diagnosing DNS for real#
PLAIN25.14.1 in simple words#
- Most problems blamed on DNS are not DNS. The fastest thing you can do is prove whether it is or not, in one command.
- The test is simple. Does the name turn into an address, quickly, with a sensible value?
- If yes, DNS worked, and you must look somewhere else. Stop blaming DNS.
- If no, then find out where it failed: your own machine, your resolver, or the authoritative servers.
- The main tool is
dig. It is precise, it shows everything, and it does not hide anything from you.
nslookup is older and friendlier and lies to you a little by simplifying. host is the short one for a quick answer.
- On macOS there are two extra commands you need, because macOS caches in a place the others do not touch.
- The reader’s own case is a perfect worked example, and the answer is clean: DNS was never the problem.
PLAIN25.14.2 a picture in your head#
- Think of a parcel that never arrived.
- The first question is not “was it stolen”. It is “did the address get written on it correctly”.
- If the label on the tracking record shows the right house number, then the address lookup worked and the parcel was lost on the road.
- If the label shows no address at all, the failure happened at the desk before the parcel ever moved.
- Those are two entirely different investigations, and doing them in the wrong order wastes hours.
- In DNS the label is the address
curl prints before it starts connecting.
Where this comparison breaks: with a parcel you can ask the depot what happened. On the internet, a silent drop tells you nothing at all, and the absence of any reply is itself the most common evidence you will get. You must reason from what did not happen.
PLAIN25.14.3 a worked example#
- Here is the reader’s own session, and the exact line that settles it.
$ curl -v https://github.com
* Trying 20.207.73.82:443...
... 15 seconds of nothing ...
* Connection timed out after 15001 milliseconds
- Look at the first line.
curl printed an IP address.
- To print that address,
curl had to resolve github.com first. It did, and it did so fast enough that the delay is not visible.
- Therefore DNS succeeded. Completely. Before the timeout ever started.
- The 15 seconds of silence happened during the TCP connection attempt, which is a later and separate step.
- This is the single most useful diagnostic habit in networking: read whether your tool printed a name or a number. A number means resolution finished.
- For contrast, a genuine DNS failure looks like this, and it fails in under a second rather than after fifteen.
$ curl -v https://githubb.com
* Could not resolve host: githubb.com
* Closing connection
curl: (6) Could not resolve host: githubb.com
- Different message, different timing, different layer, different fix.
PLAIN25.14.4 what is really happening inside#
- Work down the chain, one layer at a time, and stop at the first thing that fails.
- Layer one, your own cache. Ask twice and see if the answer is instant. If a stale answer is suspected, flush it.
- Layer two, your configured resolver. Ask it directly by name, with
@.
- Layer three, a different resolver. If
1.1.1.1 fails and 8.8.8.8 works, the problem is your resolver or the path to it, not the domain.
- Layer four, the authoritative servers. Ask them directly. If they answer and your resolver does not, the problem is in between, often DNSSEC.
- Layer five, the delegation itself. Check that the NS records at the parent match the NS records in the zone.
- Each of those is one command, and the whole sequence takes under a minute.
TECHNICAL25.14.5 the engineer’s version#
- The
dig flags that actually matter, with what each is for.
dig github.com A # the full, normal query
dig +short github.com # just the answer, for scripts
dig +noall +answer github.com # answer section only, with TTL
dig @1.1.1.1 github.com # ask a specific resolver
dig @dns1.p08.nsone.net github.com # ask the authoritative server
dig +trace github.com # walk the whole delegation chain
dig +norecurse @1.1.1.1 github.com # cache hit test, RD cleared
dig +dnssec github.com # request signatures, see AD flag
dig +tcp github.com # force TCP instead of UDP
dig -x 20.207.73.82 # reverse lookup
dig github.com ANY # mostly useless now, see below
dig +nssearch github.com # find and query all its NS
+trace is the one to reach for when a delegation looks wrong. It shows every referral, so you can see exactly which level gives the bad answer.
+norecurse against a recursive resolver is the cache test. If you get a full answer with the RD bit clear, it was cached. If you get nothing, it was not.
dig ANY is largely dead. RFC 8482, January 2019, allows servers to return a minimal response to ANY queries, and Cloudflare and others do exactly that, because ANY was heavily used for amplification attacks.
- The other tools:
| dig |
Everything, precisely |
Verbose by default |
| host |
One quick answer |
Hides detail |
| nslookup |
Interactive, on Windows |
Own resolver logic |
| dscacheutil |
macOS cache view |
Not the whole cache |
| scutil –dns |
Real macOS config |
Long output |
nslookup deserves the warning. It has its own resolution behaviour and does not always use the system resolver the way applications do, so an answer from nslookup is not proof that an application will get the same.
- macOS cache handling, and both lines are needed:
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder
- A single command that separates DNS from connectivity, because it does the two steps in order and reports each one:
dig +short github.com && \
nc -vz -w 5 $(dig +short github.com | head -1) 443
- If the first part prints an address and the second part times out, DNS is fine and the transport is not. That is precisely the reader’s situation.
- Applied to the reader’s session, stated as findings:
github.com resolved to 20.207.73.82. Resolution succeeded.
- The address is verifiably Microsoft’s, registered and announced by AS8075, and geolocates to Pune, near the reader.
curl printed the address and then received nothing for 15 seconds.
- The traceroute reached Microsoft routers in Pune and then stopped.
- The same request succeeded immediately over mobile data.
- Therefore DNS worked perfectly and can be excluded with confidence. The fault lies on the path between the reader’s fixed line and that address.
- Be careful about the last step. The evidence supports a silent drop somewhere on that path. It does not identify who dropped it, and it does not support saying the server was down, because the same address answered fine over a different access network minutes later.
WORDS25.14.6 remember these#
- dig — the standard DNS query tool — domain information groper, from BIND, showing the full message including flags and timings.
+trace — walk the tree yourself — dig mode that issues iterative queries from the root and prints every referral.
+short — answer only — dig output mode giving bare record data, suitable for scripts.
+norecurse — ask without asking for work — clears the RD bit, used to test whether a resolver already holds an answer in cache.
- mDNSResponder — the macOS resolver service — the system daemon handling both unicast DNS caching and Multicast DNS.
25.98 Common wrong ideas#
- Wrong: my computer walks the DNS tree and asks the root servers. Right: your computer asks one resolver, once. The resolver walks the tree. Your machine almost never speaks to a root server in its whole life.
- Wrong: there are thirteen root servers. Right: there are thirteen root server names and addresses, answered by over 1,900 physical instances worldwide, 2,003 of them on 13 August 2026.
- Wrong: a DNS change has to propagate around the world. Right: nothing is pushed anywhere. The change is live immediately at the authoritative servers. You are waiting for other people’s caches to expire.
- Wrong: TTL guarantees how long an answer is kept. Right: TTL is a maximum. A cache may drop an answer sooner, and some browsers and applications ignore short TTLs entirely.
- Wrong:
www.example.com and example.com are the same name. Right: they are two different names. They often point at the same place, but only because somebody configured records for both.
- Wrong: I can put a CNAME at the top of my domain. Right: you cannot. The apex must hold SOA and NS records, and RFC 1034 forbids any other data alongside a CNAME. The alternatives are provider features, not standards.
- Wrong: DNSSEC encrypts my DNS queries. Right: DNSSEC signs answers so forgery can be detected. It hides nothing. Encryption is a separate thing, DNS over TLS or DNS over HTTPS.
- Wrong: using 1.1.1.1 always makes browsing faster. Right: it usually makes lookups fast, but it can give you a content server further away than your provider’s resolver would have, because location steering is based on the resolver, not on you.
- Wrong: the reverse lookup of an address should give back the name you started with. Right: forward and reverse are controlled by different parties and often disagree, and many addresses publish no reverse record at all. The reader’s own
20.207.73.82 publishes none.
- Wrong: a SERVFAIL means the server is down. Right: it means the resolver could not produce an answer, and by far the most common cause today is a DNSSEC validation failure.
25.99 Chapter summary in 20 lines#
- DNS turns names people remember into numbers machines route to.
- Before it, one hand-edited file,
HOSTS.TXT, was copied by every machine from Stanford Research Institute, and it could not scale.
- Paul Mockapetris designed DNS in 1983, published as RFC 882 and RFC 883, replaced in November 1987 by RFC 1034 and RFC 1035, still the base today.
- Names are a tree read right to left, from an invisible root written as a single dot, through top level domains, down to whatever you create.
- Four participants: a stub resolver in your machine, a recursive resolver that does all the work, and authoritative servers in three tiers.
- Your machine asks once and waits. The recursive resolver does the running around. That single sentence prevents most confusion about DNS.
- A cold lookup of
github.com takes about eight packets and roughly 90 milliseconds; a warm one takes two packets and under 10 milliseconds.
- Thirteen root names, A to M, run by twelve organizations, served by 2,003 instances as of 13 August 2026, using anycast. Thirteen was a 512-byte limit.
- Record types each answer a different question: A and AAAA for addresses, CNAME for aliases, MX for mail, NS for delegation, SOA for zone settings.
- A CNAME cannot sit at the apex of a domain, because SOA and NS must be there and a CNAME excludes all other data. This catches everyone once.
- Caching is what makes DNS survive. Every answer carries a TTL, which is a promise of a maximum reuse time, not a guarantee.
- Lower the TTL at least two days before a migration, make the change, then raise it again. There is no propagation, only expiry.
- Your resolver normally arrives by DHCP option 6 from the router. The reader overrode this and uses
1.1.1.1, launched by Cloudflare on 1 April 2018.
- Public resolvers trade local knowledge for scale and privacy. EDNS Client Subnet, RFC 7871, partly restores the location signal, at a privacy cost.
- Different people get different answers for two separate reasons: anycast at the routing layer, and geographic or latency steering at the DNS layer.
- The reader’s
github.com resolved to 20.207.73.82, inside 20.192.0.0/10, registered to Microsoft and announced by AS8075.
- That is correct: Microsoft acquired GitHub for 7.5 billion dollars, announced 4 June 2018 and closed 26 October 2018, and fronts its traffic.
- On the wire DNS is UDP port 53, a 12-byte header and four sections, with a 16-bit query ID that made the 2008 Kaminsky cache poisoning attack possible.
- DNSSEC signs answers, from the root signed on 15 July 2010; DNS over TLS on port 853 and DNS over HTTPS on port 443 encrypt them. They are separate.
- In the reader’s own fault, DNS worked perfectly: the name resolved fast to a correct nearby address, so the failure was definitely somewhere later.