By the end you'll know
- What DNS does, and who your computer asks
- How a lookup travels from the root of the internet down to one name
- The common record types: A, AAAA, CNAME, NS, MX and TXT
- What a TTL is, and why DNS changes don't reach everyone at once
- How to look up any name yourself with
dig
Where you are
In Lesson 1, every request started with the same step: curl turned the name api.civicgrid.org into the addresses 104.21.69.165 and 172.67.210.139. Since then you've learned what those addresses are (Lesson 2), how they're grouped into ranges (Lesson 3), and how data reaches the right program once it gets there (Lesson 4).
This lesson goes back to that first step and opens it up. It's called DNS (Domain Name System), and Lesson 4 gave you a hint about it: it usually runs over UDP, on port 53.
A contacts list for the internet
You don't remember your friends' phone numbers. You tap a name in your contacts, and your phone looks up the number. DNS is that contacts list for the whole internet: you use names, because names are for people, and DNS finds the address, because addresses are what computers use.
The difference is that no single phone holds the whole internet's contacts. There are hundreds of millions of names, they change all the time, and each one is looked after by whoever owns it. So DNS is spread out: lots of servers, each one responsible for its own part of the list, and a way of finding which server knows which part.
Ask a name yourself
The tool for looking things up is dig, which comes with macOS and most Linux systems. (On Linux, if it's missing, it's in a package usually called dnsutils or bind-utils. On Windows, use WSL, or the similar nslookup command.) Ask for CivicGrid's API:
dig api.civicgrid.org
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11289
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;api.civicgrid.org. IN A
;; ANSWER SECTION:
api.civicgrid.org. 300 IN A 104.21.69.165
api.civicgrid.org. 300 IN A 172.67.210.139
;; Query time: 23 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
A few lines are trimmed from the top. It looks busy, but there are only four things to read:
status: NOERRORmeans the name exists and an answer came back.- The question section is what you asked: the
Arecords, meaning IPv4 addresses, forapi.civicgrid.org. - The answer section has one line per answer: the name, a number (
300, explained below),INfor internet, the record typeA, and the address. The same two addresses curl found in Lesson 1. SERVERsays who answered:192.168.1.1, on port 53. That's the home router from Lesson 2, and port 53 from Lesson 4's table.
Most of the time you only want the answer, so dig has a short form:
dig +short api.civicgrid.org
104.21.69.165
172.67.210.139
Who actually knows the answer
Your router didn't make that answer up, and it didn't know it in advance either. It's what's called a resolver: a server whose job is to find answers for you. Yours is probably your router, which passes questions on to your internet provider's resolver. Some people use public ones instead, like Cloudflare's 1.1.1.1 or Google's 8.8.8.8. You can ask a particular resolver by putting @ and its address first:
dig @1.1.1.1 +short api.civicgrid.org
The same two addresses come back, from a different resolver. To find the answer the first time, a resolver walks down the name from right to left. Names are really read backwards: api.civicgrid.org is "in .org, the one called civicgrid, the part called api". There's even an invisible dot at the end, which dig shows you: api.civicgrid.org.. That final dot is the root, the very top of DNS.
dig +trace does the walk itself, so you can watch each step:
dig +trace api.civicgrid.org
The real output is long, so this is trimmed to the important lines. The many lines about DNSSEC, which signs answers so they can't be faked, are left out:
. 501565 IN NS a.root-servers.net.
. 501565 IN NS b.root-servers.net.
;; Received 1097 bytes from 192.168.1.1#53(192.168.1.1) in 8 ms
org. 172800 IN NS a0.org.afilias-nst.info.
org. 172800 IN NS b0.org.afilias-nst.org.
;; Received 825 bytes from 170.247.170.2#53(b.root-servers.net) in 11 ms
civicgrid.org. 3600 IN NS evelyn.ns.cloudflare.com.
civicgrid.org. 3600 IN NS aaron.ns.cloudflare.com.
;; Received 605 bytes from 199.19.56.1#53(a0.org.afilias-nst.info) in 176 ms
api.civicgrid.org. 300 IN A 172.67.210.139
api.civicgrid.org. 300 IN A 104.21.69.165
;; Received 78 bytes from 108.162.195.150#53(aaron.ns.cloudflare.com) in 14 ms
Read it as four short conversations. Each Received ... from line says who gave the block of answers above it:
- The resolver, your router, gave the list of root servers. There are 13 names,
atom.root-servers.net, and they're the top of the whole system. - A root server didn't know
api.civicgrid.org, but it knew who looks after.org, and said "ask them". That's anNSrecord: name server, meaning "this server is in charge of that part of the name". - A
.orgserver didn't know either, but knew thatcivicgrid.orgis looked after by two of Cloudflare's servers,evelynandaaron, and said "ask them". - Cloudflare's server gave the real answer: the two addresses. A server that holds the real records for a name, rather than pointing somewhere else, is called authoritative for it.
Nobody in the chain knew everything; each one knew who to ask next. That's what lets DNS hold hundreds of millions of names. Normally your resolver does this walk for you, and you just see the final answer.
.org, then the name servers for civicgrid.org. Then it keeps a copy, so the next person who asks gets an answer straight away.Kinds of records
An A record is only one kind. DNS holds several kinds of record for a name, and each answers a different question. These are the ones you'll meet:
| Type | Answers | Example |
|---|---|---|
A | What's the IPv4 address? | 104.21.69.165 |
AAAA | What's the IPv6 address? | 2606:4700:3034::6815:45a5 |
CNAME | Is this name another name in disguise? | www.kwamib.dev is really a Vercel name |
NS | Which servers are in charge of this domain? | aaron.ns.cloudflare.com |
MX | Where should email for this domain go? | Gmail's mail servers |
TXT | Any notes? Often proof you own the domain | A code a service asked you to add |
Ask for a type by naming it. Here's AAAA:
dig AAAA +short api.civicgrid.org
2606:4700:3034::6815:45a5
2606:4700:3035::ac43:d28b
So api.civicgrid.org does have IPv6 addresses, written in the shortened :: style from Lesson 2. Then why did Lesson 1 say IPv6: (none)? Most likely because the network it ran on had no IPv6 connection, and computers usually don't ask for IPv6 addresses they have no way to reach. The records were there; the computer just didn't ask for them.
A CNAME (canonical name) is an alias: "this name is really that name, go and look that up instead". Here's the www version of this site:
dig www.kwamib.dev
Just the answer section this time:
;; ANSWER SECTION:
www.kwamib.dev. 1799 IN CNAME f72a5c22fb5f96b6.vercel-dns-017.com.
f72a5c22fb5f96b6.vercel-dns-017.com. 300 IN A 64.29.17.1
f72a5c22fb5f96b6.vercel-dns-017.com. 300 IN A 216.198.79.1
www.kwamib.dev has no address of its own. Its record says "I'm really this long Vercel name", and that name has the addresses. The point is that Vercel can change its addresses whenever it needs to, and the site keeps working, because the alias always points at whatever Vercel's name currently says.
MX (mail exchange) records say where email goes. They come with a number, the priority, where the lowest is tried first:
dig MX +short gmail.com
40 alt4.gmail-smtp-in.l.google.com.
30 alt3.gmail-smtp-in.l.google.com.
10 alt1.gmail-smtp-in.l.google.com.
20 alt2.gmail-smtp-in.l.google.com.
5 gmail-smtp-in.l.google.com.
They come back in any order, but email to a Gmail address tries the server marked 5 first, then 10, and so on: backups built into DNS.
TTL: how long to remember
Remember the 300 in every answer line? That's the TTL (time to live): how many seconds anyone may keep a copy of this answer before asking again. Resolvers keep copies, called caching, so that the next person who asks for api.civicgrid.org gets an answer straight away, without the whole walk down from the root.
You can watch it count down. Ask twice, a few seconds apart:
dig api.civicgrid.org | grep -A3 "ANSWER SECTION"
The | from Lesson 4 passes dig's output to grep, which keeps only the line containing "ANSWER SECTION" and the three after it (-A3). The second time, a few seconds later:
;; ANSWER SECTION:
api.civicgrid.org. 295 IN A 172.67.210.139
api.civicgrid.org. 295 IN A 104.21.69.165
300 became 295: the resolver is answering from its copy, and that copy has five seconds less to live. When it reaches 0, the resolver throws the copy away and asks again. The order of the two addresses changed too, which is normal: shuffling them spreads visitors across both.
TTLs are a trade-off. A long TTL means fewer lookups and faster answers, but when you change a record, some people keep the old answer until their copy runs out. A short TTL means changes spread quickly, at the cost of more lookups. Different records on the same domain often have different TTLs: here the name servers have 3,600 seconds, an hour, and the addresses 300, five minutes.
In my real setup
Look at the NS records in the trace: civicgrid.org is looked after by Cloudflare's name servers. That's what lets Cloudflare sit in front of the API, as Lesson 1 described: I keep the records there, and the addresses they give out are Cloudflare's, not my servers'. This site, kwamib.dev, is set up differently: its name servers belong to the company I registered the domain with, and the www record is a CNAME pointing at Vercel. Run dig NS +short kwamib.dev to see. Two common ways to do the same job.
Break it on purpose
Three cases. Work out the cause before you read the explanation.
A name that doesn't exist. Misspell the API's name:
dig apii.civicgrid.org
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 20152
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; AUTHORITY SECTION:
civicgrid.org. 1800 IN SOA aaron.ns.cloudflare.com. dns.cloudflare.com. 2418182649 10000 2400 604800 1800
NXDOMAIN means "non-existent domain": the authoritative server was reached, and it says there's no such name. ANSWER: 0 agrees. The authority section shows who said so, Cloudflare's server, in a record called SOA (start of authority), which you only need to recognise. This is exactly what was behind Lesson 1's Could not resolve host: curl asked, and DNS said no such name. When you see that error, run dig on the name to check the spelling, or whether the record was ever created.
The right name, the wrong address. You can make one computer believe a name has a different address. curl's --resolve option does it for a single request:
curl -sv -o /dev/null --resolve api.civicgrid.org:443:127.0.0.1 https://api.civicgrid.org/
* Added api.civicgrid.org:443:127.0.0.1 to DNS cache
* Hostname api.civicgrid.org was found in DNS cache
* Trying 127.0.0.1:443...
* connect to 127.0.0.1 port 443 from 127.0.0.1 port 59130 failed: Connection refused
The name was fine, but curl was told its address is 127.0.0.1, your own computer, where nothing listens on port 443, so it's refused. Your computer also has a file that does this for every program: /etc/hosts on Mac and Linux. It's checked before DNS, and people add lines to it when testing, then forget them. If one machine can't reach a site that works everywhere else, cat /etc/hosts is worth a look.
Changed, but not for everyone. You move a website to a new server and update its A record, which had a TTL of 3,600. You check straight away and see the new address. Your friend still gets the old site for the next half hour. Why? Their resolver had a copy from before your change, and it's allowed to keep it until the TTL runs out: up to an hour. Nothing is broken; you just have to wait. The trick professionals use is to lower the TTL to something short, like 300, a day before a planned move, so that when the change happens, old copies expire within minutes.
Where you are now
You can now explain the whole of step 1 from Lesson 1: your computer asks a resolver, the resolver walks down from the root, and the answer comes back with a TTL that says how long to trust it. With Lessons 1 to 5 you've covered a single request end to end, from name to address to port to answer. Lesson 6 widens the view to how data travels between networks: routers, and the NAT that lets your whole home share one public address.
Check yourself
What does a DNS resolver do?
A root server is asked for api.civicgrid.org. What does it reply?
Which record type says a name is an alias for another name?
An answer has a TTL of 300. What does that mean?
dig says status: NXDOMAIN. What happened?
You changed an A record, but a friend still sees the old site. Why?
Key terms
- DNS (Domain Name System): the system that turns names into addresses, spread across many servers.
- Resolver: the server that finds answers for you, usually your router or internet provider.
- Root servers: the top of DNS. They point to the servers for each ending, like
.org. - Authoritative server: a server that holds the real records for a name.
- Record: one piece of DNS information, like an
Arecord for an address or anMXrecord for email. - CNAME (canonical name): a record that says one name is an alias for another.
- TTL (time to live): how many seconds an answer may be kept and reused.
- NXDOMAIN: the answer when a name doesn't exist.
Go deeper
- Cloudflare's Learning Center on what DNS is (opens in a new tab), with more on resolvers and the root.
- Julia Evans's comic life of a DNS query (opens in a new tab), the same journey on one page.