24.4 DNS: Resolution, Recursive Resolvers, and /etc/resolv.conf
Right, let’s talk about DNS. You use it every second you’re online, and it’s probably the single biggest “wait, how does that actually work?” protocol on the internet. It’s the phonebook of the internet, but that analogy is so tired it needs a nap. Think of it more like a massively distributed, hierarchical, cached key-value store that translates human-friendly names like example.com into machine-friendly IP addresses like 93.184.216.34. And it works so well that you only notice it when it breaks, which, unfortunately, is more often than any of us would like.
The Resolution Process: It’s Recursive, Not Recursive
When you type news.ycombinator.com into your browser and hit enter, your machine doesn’t just magically know where to go. It goes on a little journey, asking a series of very specific questions. This process is called recursive resolution, which is a terrible name because the server doing the heavy lifting is called a recursive resolver, and it’s not actually using recursion in the programming sense. It’s just iteratively asking other servers until it gets an answer. Computer science terminology, everyone.
Here’s the play-by-play:
- Your Stub Resolver: This is the little library on your computer (like
glibcon Linux). It gets the request from the browser and checks its local cache. Nothing? Its job is basically to be a middleman. It looks at/etc/resolv.conf(we’ll get to that mess soon) to find out which recursive resolver it should bother. It then packages up the question and sends it to that resolver, saying “hey, handle this for me.” - The Recursive Resolver (e.g., your ISP’s, Cloudflare’s
1.1.1.1, or Google’s8.8.8.8): This is the workhorse. It has its own cache, so if someone else using1.1.1.1asked fornews.ycombinator.comrecently, it can answer immediately. If not, it begins its iterative quest:- It asks one of the 13 root servers: “Hey, who knows about
.com?” - The root server responds with a referral: “I don’t know, but here are the IPs for the
.comTop-Level Domain (TLD) servers. Go bother them.” - It asks a
.comTLD server: “Hey, who knows aboutycombinator.com?” - The TLD server responds: “Not my problem. Here are the nameservers for
ycombinator.com. They’re authoritative for that domain.” - Finally, it asks one of
ycombinator.com’s authoritative nameservers: “Okay, what’s the IP fornews.ycombinator.com?” - The authoritative server, which actually holds the record, responds with the final answer: “A record is
209.216.3.23”.
- It asks one of the 13 root servers: “Hey, who knows about
- The recursive resolver stores this result in its cache (respecting the TTL value set by the domain owner), sends the answer back to your stub resolver, which also caches it, and finally hands it to your browser. Phew. All this happens in milliseconds. It’s a miracle.
/etc/resolv.conf: The File of Sorrows
This is the file your stub resolver uses to figure out who to ask. It seems simple, but it’s a notorious source of pain because approximately seventeen different programs on a modern Linux system think they are the boss of it and will rewrite it for you. It’s a political battleground in a text file.
A basic resolv.conf looks deceptively simple:
# This is a comment. Hope you enjoyed it, because it might get overwritten.
nameserver 192.168.1.1
nameserver 1.1.1.1
options rotate timeout:1 attempts:1
The nameserver lines list the recursive resolvers to use, in order of preference. The options line is where you can get fancy. rotate does a round-robin between the servers instead of just using the first one until it fails. timeout:1 sets the initial timeout for a query to 1 second (brutal but effective on flaky networks). attempts:1 means it will only try once before moving to the next server. This creates a “happy eyeballs”-like effect for DNS, preventing long hangs.
Now, the chaos. On a standard Ubuntu system, if you’re using NetworkManager (and you probably are), it will proudly overwrite your carefully crafted resolv.conf every time you connect to a new WiFi network, inserting the DNS server provided by the network’s DHCP. This is often your home router, which is fine, or a coffee shop’s server, which is… less fine. To actually configure this sanely, you must tell NetworkManager to stop being helpful.
# Edit the config for your connection. The 'UUID' is found via `nmcli connection show`
sudo nmcli connection edit UUID
# Set the DNS servers manually
nmcli> set ipv4.dns 1.1.1.1 8.8.8.8
# Tell NetworkManager not to use the DHCP-provided DNS
nmcli> set ipv4.ignore-auto-dns yes
nmcli> save
nmcli> quit
Alternatively, you can make the file immutable, which is the nuclear option but very effective.
sudo chattr +i /etc/resolv.conf
(Just remember chattr -i if you need to change it later, or you’ll be very confused).
The Local Hosts File: Bypassing the Madness
Before your machine even thinks about asking a DNS server, it checks a local file: /etc/hosts. This is your own private, authoritative override for the entire internet. It’s dead simple: IP address on the left, hostname(s) on the right.
# This is a classic, but it's for IPv4 loopback
127.0.0.1 localhost
# This is its IPv6 counterpart
::1 localhost ip6-localhost ip6-loopback
# Want to block a distracting website by pointing it to nowhere?
0.0.0.0 www.reddit.com
# Working on a new project and need to test with a real domain?
192.168.1.150 my-cool-new-app.com staging.my-cool-new-app.com
The hosts file is your first line of defense, your testing playground, and sometimes the cause of “I’m sure I fixed the DNS, why isn’t it working?!” headaches. Always check it. getent hosts <hostname> is a great command to see where a hostname resolves after the hosts file has had its say.