Type github.com in the browser — within milliseconds the IP 140.82.114.4 comes back. What happens in between? DNS resolves names through a four-step hierarchical lookup: root → TLD → authoritative server → resolver. Add TTL caching and the move to DNS-over-HTTPS, and DNS gets interesting. This guide walks the internals.
The DNS hierarchy
. ← root (the trailing dot, usually omitted)
├── com. ← TLD (top-level domain)
│ ├── github. ← second level
│ │ └── (A record: 140.82.114.4)
│ ├── google.
│ └── ...
├── kr.
│ ├── co.kr.
│ │ └── naver.co.kr.
│ ├── or.kr.
│ └── go.kr.
├── org.
│ ├── wikipedia.
│ └── ...
└── ...Domain names are a tree, read right-to-left. In www.github.com. the trailing dot is root, com is TLD, github is the second level, www is the host.
A single query — four steps
User: what's the IP of github.com?
↓
Browser → OS resolver (/etc/resolv.conf)
↓
OS → ISP's recursive resolver (e.g. 168.126.63.1 KT, or 1.1.1.1)
↓
The recursive resolver does:
1. Ask a root server
"who is responsible for .com?"
↓
One of the 13 root servers (a-m.root-servers.net)
↓
Reply: "com's nameserver = a.gtld-servers.net"
2. Ask the .com TLD server
"who is responsible for github.com?"
↓
Reply: "github.com's nameserver = ns-1283.awsdns-32.org"
3. Ask the authoritative server
"what's github.com's A record?"
↓
Reply: "A 140.82.114.4 TTL=60"
4. Recursive resolver replies to the user
"140.82.114.4"The recursive resolver does the heavy lifting; the client asks once. That split is what makes DNS caching effective.
Recursive vs authoritative
- Authoritative — the "official" source for a specific zone (like github.com). Operated by the domain owner.
- Recursive resolver — follows queries from client all the way to authoritative. Run by ISPs, Cloudflare (1.1.1.1), Google (8.8.8.8), or your company's network.
Recursive resolvers cache responses, so the second query is instant.
Record types — the essential nine
| Type | Purpose | Example |
|---|---|---|
A | IPv4 address | github.com → 140.82.114.4 |
AAAA | IPv6 address ("quad-A") | github.com → 2a01:4f8::1 |
CNAME | Alias to another name | www.example.com → example.com |
MX | Mail server | example.com → mail.example.com (priority 10) |
TXT | Arbitrary text (SPF, DKIM, verification) | "v=spf1 include:_spf.google.com ~all" |
NS | Nameservers for this zone | example.com NS ns1.example.com |
SOA | Zone metadata (serial, TTL, etc.) | SOA ns1.example.com hostmaster... 2024010101 |
SRV | Service location (port / priority / weight) | _sip._tcp.example.com → 10 60 5060 sip.example.com |
CAA | Allowed CA(s) for cert issuance | example.com CAA 0 issue "letsencrypt.org" |
PTR | Reverse lookup (IP → domain) | 4.114.82.140.in-addr.arpa → github.com |
TTL — the caching dial
Every record carries a TTL (in seconds) — how long resolvers may cache the answer:
github.com. 60 IN A 140.82.114.4
│
└─ TTL = 60s, then re-queryTrade-off:
- Low TTL (60s) — changes propagate fast, but more lookups
- High TTL (86400 = 24h) — fewer lookups, slower to change
Operational pattern:
- Regular A records: 300-3600 (5 min - 1 hour)
- Lower TTL to ~60 before a planned migration
- Stable records (NS): 86400
CNAME gotchas
www.example.com. CNAME example.com.
example.com. A 203.0.113.5
That's fine — www → example.com → real IP.Restrictions:
- No CNAME at the apex —
example.comitself can't be a CNAME. It would collide with MX / NS / SOA. - Route 53 ALIAS / Cloudflare ANAME flattening offer the same effect at the apex
- CNAME chains are allowed but stay shallow (1-2 hops)
MX records — mail routing
example.com. MX 10 mail1.example.com.
example.com. MX 20 mail2.example.com.
│
└─ priority. lower = tried first.
mail1 down → fall back to mail2.SPF / DKIM / DMARC also live in TXT:
SPF: "v=spf1 include:_spf.google.com ~all"
DKIM: selector._domainkey.example.com TXT "v=DKIM1; p=...."
DMARC: _dmarc.example.com TXT "v=DMARC1; p=reject"DNS over UDP, TCP, HTTPS
- UDP port 53 by default — queries are small, no connection overhead
- Falls back to TCP for responses > 512 bytes — UDP packet limit. DNSSEC responses trigger this.
- DNS-over-HTTPS (DoH, RFC 8484) — DNS over HTTPS. Prevents plaintext UDP eavesdropping / spoofing. Firefox / Chrome / 1.1.1.1 / 8.8.8.8 support it.
- DNS-over-TLS (DoT, port 853) — DNS over TLS. Similar to DoH on a separate port.
DNSSEC — defense against spoofing
Plaintext DNS lets the ISP, your café Wi-Fi, or anyone in the path forge responses. github.com queries get the attacker's IP instead of GitHub's.
DNSSEC signs every response:
github.com. A 140.82.114.4
github.com. RRSIG A 13 2 60 ...signature...
Resolver verifies the signature:
Fetch github.com's DNSKEY (public key)
Verify
Failure → respond SERVFAILAdoption is slow — complicated to run, easy to break. .gov / .mil and some EU mandates push it. Public domain coverage sits around 10%.
DNS debugging tools
dig github.com # default A record
dig github.com AAAA # IPv6
dig github.com MX # mail server
dig +trace github.com # full hierarchy trace
dig @8.8.8.8 github.com # ask a specific resolver
# Windows
nslookup github.com
nslookup -type=MX example.com
# Web tools
https://www.whatsmydns.net/ ← global propagation checkAfter a DNS change — wait the TTL, then check from multiple regions. whatsmydns.net queries 50+ resolvers simultaneously.
Common pitfalls
1. Stale DNS cache
OS, browser, and ISP each cache independently. Even after the TTL passes, some caches lag. ipconfig /flushdns (Win), sudo dscacheutil -flushcache (Mac).
2. CNAME at the apex
Trying to CNAME example.com itself violates DNS rules. Use Route 53 ALIAS or Cloudflare CNAME flattening.
3. NS / A mismatch
# Registrar configures NS:
example.com NS ns1.cloudflare.com.
# But the Cloudflare zone has no A record for example.com
→ "DNS resolution failed"Registrar NS settings have to match nameserver zone data — especially around transfers.
4. TTL traps
You lowered TTL to 60 before a migration, but downstream caches still hold the old longer TTL → some users see the old IP for days. Lowering TTL needs its own propagation window first.
5. SPF over-include
SPF allows at most 10 lookups (include depth). Stack too many include: entries and you hit PermError. Carriers silently drop the mail.
References
- RFC 1034 / 1035 (DNS basics) — datatracker
- RFC 8484 (DoH) — datatracker
- DNS visualized as a comic — howdns.works
- DNSSEC quick reference — Internet Society
Summary
- DNS = domain → IP, via a hierarchy: root → TLD → authoritative → resolver.
- Recursive resolvers do the lookup work and cache the answers. Authoritative servers are run by zone owners.
- Core records — A / AAAA / CNAME / MX / TXT / NS / SOA / SRV / CAA. Each has its own purpose.
- TTL governs cache time. Shorter = changes propagate faster, more queries.
- CNAME can't sit at the apex. ALIAS / CNAME flattening fakes it.
- UDP 53 by default; large responses use TCP; DoH/DoT bring encryption.
- DNSSEC signs answers to prevent spoofing — slow adoption, ~10% of domains.
- Debug with dig / nslookup / whatsmydns.net. Honor the TTL when waiting for changes.
- Try it: IP / CIDR Calculator to inspect the resulting IP; URL Parser to pull the host out of a URL.