7.1 DNS Resolution, Records, and Cache Boundaries
DNS is a hierarchical distributed database. It holds more than name-to-IP mappings: a name can have several resource record sets (RRsets) for addresses, mail routing, delegation, service discovery, or domain-control verification.
1. Stub resolver doesn't traverse the root on its own
A typical client path:
application
|
OS / runtime stub resolver
|
recursive resolver
|-- root server: referral to a TLD
|-- TLD server: referral to an authoritative zone
`-- authoritative server: answer or authoritative negative answerApplications usually call an OS or runtime name-service interface. Depending on platform configuration, it can consult hosts files, local caches, or enterprise naming services before passing DNS queries to a recursive resolver. These steps are not necessarily all performed by the DNS stub itself. The recursive resolver uses its cache to decide whether root, TLD, and authoritative queries are needed.
Root and TLD servers normally return referrals instead of resolving the full name. NS records identify the next name servers; necessary glue addresses break circular dependencies. If example.test is served by ns.example.test, a resolver needs an address before it can query that zone. Glue bootstraps resolution; it is not itself proof that the address passed DNSSEC validation.
13 root servers refers to 13 root server identifiers (A–M), not 13 physical machines worldwide. These services are delivered via anycast across multiple locations.
2. Recursive Query and Iterative Resolution
A client generally asks its recursive resolver for a final answer or error. The resolver can query authoritative servers iteratively, following each referral, or forward the request to another recursive resolver according to configuration.
# Query the configured resolver
dig www.example.com A
# Follow referrals from the root to demonstrate iterative resolution
dig +trace www.example.com A
# Query a specified recursive resolver
dig @1.1.1.1 www.example.com AAAAdig +trace does not replay an earlier user query. It obtains root-server information, then follows referrals from this machine; with trace enabled, @server affects only the initial root NS query. The real recursive resolver may use cached data, forwarding, QNAME minimization, or another path. These commands generate real DNS traffic; choose a permitted resolver in managed networks.
3. Records are RRsets, Not Single K/V Pairs
| Type | Data under owner name | Common use cases |
|---|---|---|
A | IPv4 address | address resolution |
AAAA | IPv6 address | address resolution |
CNAME | canonical name | aliasing |
MX | preference + mail exchanger name | mail routing |
NS | authoritative name server name | zone delegation and authority |
TXT | one or more character strings | domain verification, SPF records, etc. |
SOA | primary name server, serial number, and zone timer | zone authority and negative caching data |
CAA | CA authorization policy | restricts which CAs are allowed to issue certificates for a domain |
An RRset groups records with the same owner name, class, and type. One A RRset can contain several IPv4 addresses; AAAA is a separate set. Do not treat each address as a separate RRset or rely on answer order as a stable priority. A connection library may also interleave IPv6 and IPv4 attempts.
In the DNS data model, an owner name that is a CNAME should not contain any other standard record types (with DNSSEC-related records being a notable exception). This creates a conflict between a zone apex CNAME and required SOA/NS records. Some DNS providers offer ALIAS / ANAME / flattening features. These are provider-specific capabilities, not standard CNAME record types.
CNAME chains may increase lookup overhead, but it cannot be asserted that they always result in an additional network round trip: resolvers can hit caches, and authoritative responses may include related data.
4. TTL Controls Cache Freshness, Not Global Clock Synchronization
Authoritative records carry TTLs, and caches count down their remaining lifetime. Expiry calls for a refresh, not a global deletion broadcast. RFC 8767 allows a resolver configured for serve-stale to return expired data under controlled conditions when refresh fails, with limits on stale retention and response TTL. This does not make the old value the latest authoritative data.
TTL introduces a trade-off:
- A longer TTL reduces the number of authoritative queries and lowers resolver latency, but retains answers from before a change for longer;
- A shorter TTL allows new queries to detect changes more quickly, but increases dependency on DNS services and query load;
- Resolvers and applications may implement minimum or maximum cache policies, meaning actual behavior cannot be reliably predicted solely from the authoritative TTL;
- Existing TCP/TLS connections do not automatically migrate to new addresses when a DNS TTL expires.
For a planned migration, lower the TTL, confirm authoritative servers publish it, wait at least the previous TTL window, then switch addresses. Lowering 3600 seconds to 60 does not shorten a record cached just before the change; it may remain for nearly an hour. Waiting only 60 seconds is insufficient. Retain the old endpoint while observing traffic, including application caches, long-lived connections, and serve-stale behavior.
5. Negative caching can also cause newly created names to temporarily be absent
NXDOMAIN and NODATA can both be negatively cached. Under RFC 2308, the SOA TTL in an authoritative negative response is min(SOA record TTL, SOA.MINIMUM), then counts down normally. This example only calculates ordinary negative-cache lifetime; it does not implement a resolver or serve-stale:
soa_ttl = 3600
soa_minimum = 300
negative_ttl = min(soa_ttl, soa_minimum)
for elapsed in [0, 120, 300]:
remaining = max(0, negative_ttl - elapsed)
print(elapsed, remaining)
# 0 300
# 120 180
# 300 0If a resolver cached NXDOMAIN before a name was created, creating its record does not erase that cached answer. Distinguish the following results:
- NXDOMAIN: the name does not exist;
- NODATA: the name exists, but no resource records (RRset) of the queried type are available;
- SERVFAIL: the resolver was unable to obtain a valid response, which may involve DNSSEC validation, upstream failure, or a protocol error.
NODATA has no dedicated RCODE. It is inferred from NOERROR, absence of the requested data, and authoritative-zone information; not every empty answer is NODATA. NXDOMAIN caching is scoped to name and class, while NODATA also distinguishes query type. An A record with no AAAA record does not imply a nonexistent name.
6. Enumerate IPv4 and IPv6 Addresses Using System Resolver
Python getaddrinfo() uses platform name-service configuration, so results need not come from DNS and the socket API exposes no authoritative TTL. This code deduplicates IPv4/IPv6 addresses while retaining IPv6 scope IDs, avoiding accidental merging of the same link-local address on different interfaces:
#!/usr/bin/env python3
import socket
import sys
def resolve_stream_addresses(host: str, service: str = "443") -> list[str]:
results = socket.getaddrinfo(
host, service, family=socket.AF_UNSPEC,
type=socket.SOCK_STREAM, proto=socket.IPPROTO_TCP,
)
addresses: list[str] = []
seen: set[tuple[int, str, int]] = set()
for family, _type, _proto, _canonname, sockaddr in results:
address = sockaddr[0]
scope = sockaddr[3] if family == socket.AF_INET6 else 0
key = (family, address, scope)
if key not in seen:
seen.add(key)
label = "IPv6" if family == socket.AF_INET6 else "IPv4"
suffix = f"%{scope}" if scope and "%" not in address else ""
addresses.append(f"{label} {address}{suffix}")
return addresses
if __name__ == "__main__":
host = sys.argv[1] if len(sys.argv) > 1 else "localhost"
try:
for item in resolve_stream_addresses(host):
print(item)
except socket.gaierror as error:
raise SystemExit(f"resolution failed: {error}")The default is localhost; address families and order depend on machine configuration. A numeric address such as 127.0.0.1 checks output formatting without public DNS. socket.setdefaulttimeout() neither clears caches nor sets a resolution deadline for getaddrinfo(). Repeated calls cannot reliably isolate cold and warm DNS caches. Use dig or a DNS library to inspect TTLs or select resolvers, and record the environment.
7. DNS Transport and Security Boundary
Classic DNS supports both UDP and TCP; general-purpose implementations must support TCP. EDNS(0) advertises receive capacity for UDP payloads, not a guarantee that the path carries that size without fragmentation. TC marks a truncated UDP response, normally triggering a TCP retry; packet loss may instead cause a timeout. Each DNS message over TCP has a two-byte big-endian length prefix.
DNSSEC provides origin authentication and integrity validation for DNS data, but does not encrypt query names. DoT and DoH protect the channel between the client and an encrypted DNS resolver, yet the resolver can still see the query, and these mechanisms do not automatically ensure that authoritative data receives DNSSEC validation. Each of the following must be evaluated separately:
- Client-to-resolver transport privacy;
- Resolver logging and trust policies;
- Authenticity of DNS data;
- TLS authentication within the application protocol itself.
8. Diagnosis Order
- Check the current recursive resolver. Do not assume all hosts use the same public resolver by default.
- Query both A and AAAA records separately, and record the status, answer, authority, and TTL for each.
- Directly query the authoritative server and compare the result with the recursive resolver’s answer.
- Examine the CNAME chain, delegation NS records, and glue records to ensure proper delegation.
- Distinguish between positive cache hits, negative cache entries, and existing connection reuse.
- When DNSSEC is in use, inspect validation failures. Do not treat SERVFAIL as a definitive sign that no record exists.
9. Acceptance Questions
- What roles do stub resolver, recursive resolver, and authoritative server play in the DNS hierarchy?
- Why is it unsuitable to place a CNAME record directly at the apex of a standard zone?
- Outline the step-by-step sequence for a DNS cutover: reduce TTL, wait, switch to the new endpoint, monitor the transition, and decommission the old endpoint.
- How do NXDOMAIN, NODATA, and SERVFAIL differ in their DNS response semantics?
- Why can't DNSSEC replace HTTPS for securing web traffic?
Next lesson: 7.2 CDN Caching, Origin Pulling, and Traffic Routing