DNS Fundamentals - The Internet's Phone Book
Status: Active
Last Updated: 2026-08-14
Category: Networking - Phase 1: Network Fundamentals
Prerequisites: tcp-ip-fundamentals, ip-addressing-subnets
Time: 2-3 hours
Tags: dns, resolution, records, ttl, authoritative, recursive, caching
Summary
How names become addresses: the DNS hierarchy from root servers down to your local resolver, every record type you'll actually encounter (A, AAAA, CNAME, MX, TXT, NS, SRV), the difference between authoritative and recursive servers, how caching and TTLs make lookups fast β and make changes slow to propagate. Ends with the hands-on dig skills you'll use for the rest of your career.
π― What You'll Learn
By the end of this guide, you'll understand:
- β Why DNS exists and how its hierarchy is organized
- β The complete journey of a lookup from your browser to the root zone and back
- β What every common DNS record type means and when each is used
- β Authoritative vs recursive vs caching resolvers β three different jobs
- β How TTL and caching govern "propagation"
- β
Reading
digoutput like a native speaker - β Where to point your own machines' resolvers (and what breaks when you don't)
Table of Contents
- The Problem DNS Solves
- The Hierarchy
- Anatomy of a Lookup
- Record Types You'll Actually Use
- Authoritative vs Recursive
- TTL, Caching, and "Propagation"
- dig: The Only Tool You Need
- Choosing Resolvers for Your Machines
- Hands-On Exercises
- Common Gotchas
- Next Steps
π Related
The Problem DNS Solves
Computers route by numbers; humans remember names. DNS (Domain Name System) is the globally distributed database that translates between them β example.com β 93.184.216.34.
Three properties make DNS one of the internet's great designs:
- Distributed β no single server knows everything; responsibility is delegated down a tree
- Cached everywhere β answers are remembered at many layers so the root zone isn't hammered billions of times per second
- Delegated β you control your domain's records because the
.comzone points at your nameservers
You will interact with DNS constantly in self-hosting: pointing domains at your servers, creating internal names for services, running your own resolver (pihole-setup), and debugging why "it works on my laptop but not the server."
The Hierarchy
DNS namespaces are organized as an inverted tree:
. (root)
βββββββββββββ¬ββββ΄βββββββββ¬ββββββββββββββ
com net org dev
β β β β
example.com example.net example.org fogserv.dev
β
www.example.com Β· mail.example.com Β· api.example.com
Reading a FQDN (fully qualified domain name) right-to-left climbs the tree: www.example.com. = "www, inside example, inside com, inside root." That trailing dot is real β it's the root β but everyone omits it.
Delegation In Action
Nobody "owns" the whole tree. Instead:
| Zone | Who runs it | What they know |
|---|---|---|
. (root) |
13 operator identities (a.root-servers.net β¦ m.root-servers.net), anycasted to thousands of instances worldwide | Which servers answer for every TLD |
com |
Verisign + others | For each .com domain: which nameservers are authoritative |
example.com |
Whoever registered it (that's you) | Every record inside the domain |
When you buy mydomain.com, you tell the registrar which nameservers to publish in the .com zone (NS delegation). From then on, the world asks your nameservers β or whoever hosts DNS for you (Cloudflare, Route53, your own bind).
# See the delegation chain yourself:
dig com NS # who serves .com?
dig example.com NS # who is authoritative for example.com?
Anatomy of a Lookup
What happens, in full, the first time any machine resolves www.example.com:
Your browser Your resolver (e.g. 192.168.1.1 / 1.1.1.1)
β β
β 1. "www.example.com A?" β
β ββββββββββββββββββββββββββββββββββββββΊ β
β β 2. cache miss β ask root
β β ββ "www.example.com A?" βββΊ root
β β ββ "ask .com, here are its servers" ββ
β β 3. ask .com
β β ββ "www.example.com A?" βββΊ a.gtld-servers
β β ββ "ask ns1.example.com" ββ
β β 4. ask authoritative
β β ββ "www.example.com A?" βββΊ ns1.example.com
β β ββ "93.184.216.34, TTL 3600" ββ
β βββ 93.184.216.34 (cached TTL 3600) ββ β
Key observations:
- Your machine never talks to the root servers. It asks exactly one server: its configured recursive resolver, which does the legwork (this style is called iterative resolution).
- Every answer is cached along the way, honoring its TTL. The next lookup of anything under
.comskips step 2 entirely. - This was all UDP port 53, one small query/answer pair per hop β you watched this traffic in tcp-ip-fundamentals.
Record Types You'll Actually Use
A zone file is just a set of typed records. These cover ~99% of real work:
| Type | Purpose | Example |
|---|---|---|
| A | Name β IPv4 | www IN A 203.0.113.10 |
| AAAA | Name β IPv6 | www IN AAAA 2001:db8::10 |
| CNAME | Alias β another name | blog IN CNAME www (then resolve www again) |
| MX | Mail exchanger for the domain | IN MX 10 mail.example.com. |
| TXT | Free-form text (SPF, DKIM, verification) | IN TXT "v=spf1 include:_spf.google.com ~all" |
| NS | Nameserver delegation for a zone | IN NS ns1.example.com. |
| SOA | Zone metadata (serial, refresh timers) | One per zone; mostly machinery |
| SRV | Service location (port included) | _sip._tcp IN SRV 10 5 5060 sip.example.com. |
| PTR | Reverse: IP β name | 10.113.0.203.in-addr.arpa IN PTR www.example.com. |
Rules of Thumb
- CNAME cannot coexist with other records at the same name (RFC rules; some providers bend this). The apex/root of a domain (
example.comitself) can't have a CNAME β use ALIAS/ANAME flattening if your provider offers it, or plain A records. - MX values need a trailing dot in zone files (
mail.example.com.) or they silently becomemail.example.com.example.com. Classic typo, classic outage. - SPF/DKIM/DMARC β the trio of anti-spam TXT records β matter the moment you send email from your domain. Wrong SPF = your newsletters land in spam (relevant to the KB's newsletter system).
- SRV is how services advertise "I'm on this host and port" β used by LDAP, Matrix federation discovery, Minecraft. Most web stuff doesn't need it (browsers assume 80/443).
Wildcards and Subdomain Patterns
*.apps.example.com. IN A 203.0.113.20 # anything.apps.example.com works
Wildcards pair beautifully with wildcard certificates (later: traefik-ssl-automation) β add gitlab.apps, grafana.apps without touching DNS again.
Authoritative vs Recursive
Same protocol, completely different jobs β confusing these makes docs unreadable:
| Authoritative server | Recursive resolver | |
|---|---|---|
| Answers from | Its own zone data | Cache + climbing the hierarchy |
| Knows about | Only its zones | Everything (by asking around) |
| Run by | Registrars, DNS hosts, you (bind/nsd) | ISPs, 1.1.1.1/8.8.8.8, your router, your Pi-hole |
| Question it gets | "What is <www.example.com>?" (definitive) | "What is <www.example.com>?" (best effort, cached) |
dig @ns1.example.com www.example.com # ask a specific (authoritative) server
dig @1.1.1.1 www.example.com # ask a specific (recursive) server
# Flags tell you which kind answered:
;; flags: qr aa rd ra;
# β β β ββ ra = recursion available β recursive server
# β β βββββ rd = recursion desired (your request)
# β ββββββββ aa = authoritative answer β from the source of truth
# βββββββββββ qr = query response marker
In your infrastructure both roles appear: Pi-hole acts as your local recursive-ish resolver (actually a filtering forwarder unless you add Unbound), while Traefik's DNS-01 challenges talk to your authoritative provider's API (later lessons).
TTL, Caching, and "Propagation"
Every record ships with a TTL (time to live) in seconds β how long any cache may reuse the answer.
www 3600 IN A 203.0.113.10
β
TTL = 3600s = 1 hour
The famous "DNS propagation delay" is really cache expiry: nothing pushes your change outward; caches simply serve stale answers until their TTL lapses.
Practical consequences:
- Lower TTL before planned changes. Set
300(5 min) hours ahead of a migration; raise back to3600+after things stabilize. Low TTL forever = more load on your authoritative servers and slower browsing for everyone resolving you. - Negative caching is real. NXDOMAIN ("no such name") responses also cache (per SOA minimum). A typo'd record can be sticky for minutes even after fixing.
- Serial numbers in SOA must increase on every zone edit for secondary nameservers to notice β most managed DNS handles this; hand-run bind does not.
# Watch caching happen: run twice, note query time and server path
dig www.wikipedia.org | grep -E "Query time|SERVER|flags"
dig www.wikipedia.org | grep -E "Query time|SERVER|flags"
# Second run: Query time β 1-30ms, flags include ra, no climb needed
# See remaining cache life from your resolver's view:
dig +noall +answer www.wikipedia.org
# www.wikipedia.org. 300 IN A 185.15.59.224 β 300 = seconds left in cache
Myth check: "propagation takes 48 hours" comes from ancient default TTLs. With modern TTLs, most changes are fully visible in minutes. If something still resolves wrong after an hour, suspect you edited the wrong zone/wrong nameservers β not propagation.
dig: The Only Tool You Need
dig (Domain Information Groper) is verbose, scriptable, and universal. Core patterns:
dig example.com # basic A lookup via your default resolver
dig example.com AAAA # specific record type
dig example.com ANY +noall +answer # all types (many servers restrict this now)
dig @8.8.8.8 example.com # bypass your resolver β test another one
dig +short example.com # just the answer line(s)
dig +trace example.com # replay the full rootβTLDβauth walk
dig -x 203.0.113.10 # reverse lookup (PTR)
dig example.com MX # where does its mail go?
dig example.com TXT # SPF/DKIM/domain verification
dig _dmarc.example.com TXT # DMARC policy
Reading a full answer:
; <<>> DiG 9.18 <<>> www.example.com
;; QUESTION SECTION:
;www.example.com. IN A
;; ANSWER SECTION:
www.example.com. 86400 IN A 93.184.216.34
β β β β
name TTL class the answer
;; AUTHORITY SECTION: β nameservers that vouch for this zone
;; ADDITIONAL SECTION: β bonus records (e.g., IPs of those NS)
;; Query time: 42 msec β 0-5ms after caching kicks in
;; SERVER: 192.168.1.1#53 β who actually answered you
nslookup and host do less but exist everywhere; know them for quick checks:
host example.com
nslookup example.com 1.1.1.1
Choosing Resolvers for Your Machines
Every device needs at least one recursive resolver. Options, best-practice order for self-hosters:
| Choice | Pros | Cons |
|---|---|---|
| Your own Pi-hole/Unbound (LAN IP) | Filtering, local records, full visibility | Single point of failure β always configure two |
Public: 1.1.1.1, 9.9.9.9, 8.8.8.8 |
Fast, reliable, easy | Third party sees all your lookups |
| ISP resolver (DHCP default) | Zero config | Often slow, ad-injecting, unreliable |
# Inspect what a box is actually using (three different mechanisms!):
resolvectl status # systemd-resolved (modern desktops/servers)
cat /etc/resolv.conf # classic mechanism (often symlinked to systemd)
nmcli dev show | grep DNS # NetworkManager's view
# Test whether DoT/DoH (encrypted DNS) is in play:
resolvectl status | grep -i "DNSOverTLS\|Current DNS Server"
Two failure modes worth memorizing early:
- Resolver dead β everything times out, ping-by-IP works fine. Fix: second DNS entry.
- Wrong search domain β
ssh web01triesweb01.lan.example.com.first, fails slow. Checksearch/ndotssettings when shortnames misbehave β a notorious Kubernetes/K3s latency trap (containers withndots:5generate 5Γ the lookups; relevant later in kb/containers/k0s-networking).
Local overrides for lab machines:
# Quick and dirty (until reboot/regenerate):
echo "203.0.113.10 gitlab.internal.test" | sudo tee -a /etc/hosts
# Proper: local records on your own DNS server β lesson [local-dns-records](local-dns-records)
Hands-On Exercises
# 1. Trace a domain end-to-end and watch each hop:
dig +trace fogserv.dev | tail -20
# 2. Compare answers across public resolvers (do they agree? same TTLs?)
for r in 1.1.1.1 8.8.8.8 9.9.9.9; do echo "== $r"; dig +short @$r example.com; done
# 3. Dissect a real domain's email setup:
dig gmail.com MX +short
dig gmail.com TXT +short | head -3
dig _dmarc.gmail.com TXT +short
# 4. Measure caching benefit:
time dig +stats slashdot.org | grep "Query time" # first call
time dig +stats slashdot.org | grep "Query time" # second call β see the drop?
# 5. Find your machine's resolver chain and draw it on paper:
resolvectl status || cat /etc/resolv.conf
# 6. Break DNS deliberately (in a VM!) and observe the symptom shape:
sudo resolvectl dns eth0 192.0.2.53 # black-hole resolver
curl -m5 https://example.com # note: TIMEOUT, not refused
ping -c2 93.184.216.34 # ...but IP connectivity is fine
sudo resolvectl flush-cache # restore: resolvectl revert eth0
That last exercise encodes the most valuable diagnostic reflex in this whole course: if names fail but IPs work, it's DNS. Say it out loud; you'll use it monthly.
Common Gotchas
| Symptom | Cause | Fix |
|---|---|---|
| Works by IP, times out by name | Resolver unreachable/misconfigured | dig @1.1.1.1 vs plain dig; fix /etc/resolv.conf |
| Change made, old answer persists | Cache honoring TTL | Wait out TTL; lower TTL next time pre-change |
| New subdomain instantly NXDOMAIN | Negative caching of the miss | Flush local (resolvectl flush-cache), wait negative-TTL elsewhere |
dig fine, browser fails |
Browser uses DoH to a different resolver | Check browser secure-DNS setting |
| Intermittent slow SSH/curl by hostname | Search-domain + ndots retries | Qualify names with trailing dot: ssh web01. |
| Mail not arriving anywhere | Missing/broken SPF, MX trailing-dot typo | dig yourdomain MX, dig yourdomain TXT β read them like a stranger would |
| Domain resolves externally, not internally | Split-horizon zone missing the record | Add it locally too β see local-dns-records |
| Random NXDOMAIN bursts | Resolver failover to broken upstream | Configure two resolvers; monitor with dig +stats cron job |
Next Steps
Names now resolve; make them resolve reliably and debuggably:
- network-troubleshooting β the full toolkit when any layer misbehaves
- pihole-setup β run DNS yourself, filter ads network-wide
- local-dns-records β split-horizon DNS for your internal services
π Related
- Prerequisite: tcp-ip-fundamentals, ip-addressing-subnets
- Next: network-troubleshooting
- traefik-ssl-automation β DNS-01 certificate challenges
- certificate-management β names β certificates binding
- kb/security/network-segmentation β isolating DNS infrastructure