Networking Tutorial · Core Protocols · Lesson 11 of 28
DNS
How a name like www.example.com becomes an IP address: resolvers, the DNS hierarchy, caching and TTLs.
What DNS does
DNS (Domain Name System) maps names to addresses and other data. It is a distributed database: no single server knows every name.
How a lookup works
- Your app asks the operating system, which asks a recursive resolver (your provider's, the cloud's, or a
public one such as
1.1.1.1or8.8.8.8). - If the answer isn't cached, the resolver asks a root server where
.comlives, - then a .com TLD server where
example.comlives, - then
example.com's authoritative name server, which returns the record. - The resolver caches the answer for its TTL (time to live) and returns it.
ZONES = {
".": {"com.": "a.gtld-servers.net"},
"com.": {"example.com.": "ns1.example-dns.net"},
"example.com.": {"www.example.com.": ("A", "93.184.215.14", 3600)},
}
def resolve(name):
zone = "."
for step in ["root", "TLD", "authoritative"]:
answer = next(v for k, v in ZONES[zone].items() if name.endswith(k))
print(f"ask {step:13} ({zone:12}) -> {answer}")
if isinstance(answer, tuple):
return answer
zone = next(k for k in ZONES[zone] if name.endswith(k))
print("answer:", resolve("www.example.com."))
Output
ask root (. ) -> a.gtld-servers.net
ask TLD (com. ) -> ns1.example-dns.net
ask authoritative (example.com.) -> ('A', '93.184.215.14', 3600)
answer: ('A', '93.184.215.14', 3600)TTL and caching
Every record has a TTL in seconds. Caching makes DNS fast, but it also means a change you make isn't seen everywhere until old cached copies expire. Before a migration, lower the TTL (for example to 60 s) at least one old-TTL period in advance.
cache = {}
def lookup(name, now, records):
hit = cache.get(name)
if hit and hit["expires"] > now:
return hit["ip"], "cached"
ip, ttl = records[name]
cache[name] = {"ip": ip, "expires": now + ttl}
return ip, "fresh"
records = {"api.shop.example": ("10.0.1.10", 300)}
print("t=0 ", lookup("api.shop.example", 0, records))
records["api.shop.example"] = ("10.0.9.99", 300) # we migrate the server
print("t=120", lookup("api.shop.example", 120, records), "<- old address until the TTL expires")
print("t=301", lookup("api.shop.example", 301, records))
Output
t=0 ('10.0.1.10', 'fresh')
t=120 ('10.0.1.10', 'cached') <- old address until the TTL expires
t=301 ('10.0.9.99', 'fresh')Try it
$ dig +short www.example.com
93.184.215.14
$ dig www.example.com +trace # follow the lookup from the root servers
$ nslookup www.example.com # also available on Windows
Applications cache too: the JVM, some HTTP clients and connection pools may keep using an old address long after the DNS TTL expired.
Test yourself
You will move a site to a new IP. The A record's TTL is 86400 (one day). What should you do first?
Lower the TTL a day or more before the moveChange the IP and restart the DNS serverSet the TTL to 0 at the moment of the moveNothing; DNS changes are instant
Show answer
Answer: Lower the TTL a day or more before the move
Caches keep the old record for up to the old TTL. Lower it in advance so that, at cut-over time, caches expire within minutes.