Skip to main content

DNS Resolution

Recursive DNS Resolution Step-by-Step Simulator (`example.com`)

Step 1: Check browser cache, OS `/etc/hosts`, local DNS resolver cache (e.g. 1.1.1.1 or 8.8.8.8). On cache miss, recursive query starts.

DNS Resource Record Type Inspector & Zone File Explorer
example.com.    3600    IN    A    93.184.216.34  ; Maps hostname to 32-bit IPv4 address

What is DNS?

DNS (Domain Name System) translates human-readable domain names into IP addresses (and vice versa). It is the internet's distributed phone book.

"api.example.com" β†’ DNS β†’ "93.184.216.34"

DNS is a distributed, hierarchical, cached system β€” no single server knows everything; the answer is assembled through a chain of queries.


DNS Hierarchy

. (root)
/ | \
com org net io ... (TLDs β€” Top Level Domains)
/ | \
google example amazon (SLDs β€” Second Level Domains)
/
api www mail (Subdomains)

DNS Server Types

TypeRoleExample
DNS Resolver (Recursive)Queries on behalf of clients8.8.8.8 (Google), 1.1.1.1 (Cloudflare)
Root NameserverKnows TLD nameserver addresses13 root server clusters (a–m.root-servers.net)
TLD NameserverKnows authoritative NS for domainsVerisign (for .com), ICANN
Authoritative NameserverHas the actual records for a domainRoute 53, Cloudflare, your own NS

DNS Resolution Process

Browser β†’ OS β†’ Resolver β†’ Root β†’ TLD β†’ Authoritative

User types: api.example.com

1. Browser cache: api.example.com β†’ ? (miss)
2. OS cache / /etc/hosts: ? (miss)
3. OS β†’ Resolver (e.g., 8.8.8.8):
"What is api.example.com?"

4. Resolver β†’ Root NS:
"Who handles .com?"
Root NS: "Ask a.gtld-servers.net"

5. Resolver β†’ TLD NS (a.gtld-servers.net):
"Who handles example.com?"
TLD NS: "Ask ns1.example.com"

6. Resolver β†’ Authoritative NS (ns1.example.com):
"What is api.example.com?"
Auth NS: "93.184.216.34, TTL 300"

7. Resolver caches: api.example.com β†’ 93.184.216.34 (for 300s)
8. Resolver β†’ Client: 93.184.216.34
9. Client caches result
10. Browser connects to 93.184.216.34:443

Full resolution typically takes 50–200ms; cached responses are < 1ms.


DNS Record Types

TypeNameValueUse
AIPv4 Address93.184.216.34Map hostname β†’ IPv4
AAAAIPv6 Address2606:2800:220:1::...Map hostname β†’ IPv6
CNAMECanonical Nameexample.comAlias β†’ another hostname
MXMail Exchanger10 mail.example.comEmail routing (with priority)
TXTText"v=spf1 include:..."SPF, DKIM, domain verification
NSName Serverns1.example.comAuthoritative NS for zone
SOAStart of Authorityadmin + serial + refreshZone metadata
PTRPointerexample.comReverse DNS (IP β†’ hostname)
SRVService10 20 443 api.example.comService location (gRPC, SIP)
CAACA Authorization0 issue "letsencrypt.org"Which CAs may issue SSL certs

CNAME Chains

api.example.com β†’ CNAME β†’ api-lb.cdn.example.com
api-lb.cdn.example.com β†’ A β†’ 203.0.113.50

Restriction: CNAME cannot coexist with other records at the same name
β†’ Cannot put CNAME at zone apex (example.com itself) β€” use ALIAS/ANAME

MX Records and Priority

example.com MX 10 mail1.example.com (lowest priority = preferred)
example.com MX 20 mail2.example.com (backup)
example.com MX 30 mail3.example.com (last resort)

DNS TTL (Time To Live)

TTL controls how long DNS answers are cached by resolvers and clients.

api.example.com A 93.184.216.34 TTL=300 ← cached for 5 minutes

Low TTL (30–60s):
βœ… Fast propagation when IP changes (failover, deployments)
❌ More DNS queries β†’ higher load on nameservers

High TTL (3600–86400s):
βœ… Less DNS lookup overhead, fewer queries
❌ Slow to update on IP changes

Deployment strategy:

  1. Lower TTL to 60s a few hours before a change
  2. Make the DNS change
  3. After TTL passes, raise TTL back to normal

DNS Caching Layers

1. Browser DNS cache (chrome://net-internals/#dns)
2. OS DNS cache (nscd, systemd-resolved)
3. Router/modem cache
4. ISP resolver cache (your ISP's recursive resolver)
5. Public resolver cache (8.8.8.8, 1.1.1.1)
6. Authoritative server (source of truth)
# Flush OS DNS cache
# Linux (systemd-resolved)
sudo systemd-resolve --flush-caches

# macOS
sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder

# Windows
ipconfig /flushdns

# Query DNS directly
nslookup api.example.com 8.8.8.8
dig api.example.com @8.8.8.8
dig +trace api.example.com # full resolution chain
dig -x 93.184.216.34 # reverse DNS lookup

DNS Load Balancing

DNS can distribute traffic without a dedicated load balancer.

Round-Robin DNS

api.example.com A 10.0.0.1
api.example.com A 10.0.0.2
api.example.com A 10.0.0.3

Resolver rotates the order each query:
Query 1: [10.0.0.1, 10.0.0.2, 10.0.0.3] β†’ client picks first
Query 2: [10.0.0.2, 10.0.0.3, 10.0.0.1] β†’ client picks first

Limitations: no health checking β€” if one server dies, DNS still returns it.

GeoDNS / Latency-Based Routing

Serve different IPs based on the client's geographic location:

Client in US β†’ api-us.example.com β†’ 203.0.113.10 (US servers)
Client in EU β†’ api-eu.example.com β†’ 198.51.100.20 (EU servers)

Used by: Route 53 latency-based routing, Cloudflare GeoDNS.


DNSSEC

DNSSEC adds cryptographic signatures to DNS responses to prevent spoofing.

Without DNSSEC:
Attacker intercepts DNS response β†’ returns malicious IP β†’ cache poisoning

With DNSSEC:
Zone signs records with private key β†’ DS record in parent zone
Resolver validates signature chain back to root (IANA)
Tampered responses fail signature check β†’ rejected
# Verify DNSSEC
dig DNSKEY example.com
dig +dnssec A example.com # check AD (Authenticated Data) flag

Common DNS Issues & Diagnostics

DNS Propagation

After changing DNS records, old records may be cached globally for the duration of the TTL. "Propagation" is just waiting for caches to expire.

# Check from multiple global DNS resolvers
# whatsmydns.net β€” visual global propagation check
dig @8.8.8.8 example.com A # Google
dig @1.1.1.1 example.com A # Cloudflare
dig @9.9.9.9 example.com A # Quad9

Split-Horizon DNS

Different DNS answers for internal vs external clients:

Internal client: api.example.com β†’ 10.0.0.5 (private IP)
External client: api.example.com β†’ 203.0.113.5 (public IP/load balancer)

Used for: routing internal traffic through private network, keeping internal structure private.


Java DNS Configuration

// Java caches DNS results internally β€” configure TTL
// Default: 30s positive, 10s negative

// Set in jvm options or security properties
// $JAVA_HOME/conf/security/java.security
networkaddress.cache.ttl=30 // successful lookups
networkaddress.cache.negative.ttl=10 // failed lookups

// Or programmatically:
Security.setProperty("networkaddress.cache.ttl", "30");

// Spring Boot: use DNS-aware connection pool
// HttpClient automatically re-resolves on new connections
WebClient client = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(
HttpClient.create()
.resolver(DefaultAddressResolverGroup.INSTANCE))) // DNS-aware
.baseUrl("https://api.example.com")
.build();

DNS on the Wire: UDP, TCP, EDNS and Encrypted DNS

  • Queries normally use UDP port 53. The classic limit is 512 bytes. EDNS0 raises it (up to 4096), but since the 2020 DNS Flag Day resolvers advertise about 1232 bytes to avoid IP fragmentation.
  • If the answer does not fit, the server sets the TC (truncated) bit and the client retries over TCP port 53. Zone transfers (AXFR) and large DNSSEC answers also use TCP, so blocking TCP/53 breaks DNS in subtle ways.
  • DoT (DNS over TLS, port 853) and DoH (DNS over HTTPS, port 443) encrypt the stub-to-resolver hop. Note that DoH can bypass enterprise DNS filtering, and neither one encrypts the resolver-to-authoritative hop.

Negative Caching, CNAME Rules and Record Gotchas

  • NXDOMAIN (name does not exist) and NODATA (name exists, no such type) are cached too, for the TTL given by the zone's SOA minimum / negative TTL (RFC 2308). A name created right after a failed lookup can stay "missing" for minutes.
  • SERVFAIL means the resolver could not get an answer (broken DNSSEC, unreachable authoritative servers). It is a different failure from NXDOMAIN and resolvers may retry other servers.
  • A CNAME cannot exist at the zone apex (it would conflict with the mandatory SOA and NS records) and cannot coexist with other records of the same name. Providers offer ALIAS/ANAME flattening for example.com pointing at a load balancer hostname.
  • Lowering a TTL only helps after the old TTL has expired. Before a migration, drop the TTL a full old-TTL period in advance, then cut over. Some resolvers and clients ignore low TTLs, so expect a long tail.
  • DNS-based load balancing cannot drain a node precisely. Clients cache answers and ignore health, so pair it with real health checks and low TTLs, or use an L4/L7 load balancer.
dig +trace example.com # walk root -> TLD -> authoritative
dig +norecurse example.com @8.8.8.8 # cache-only check
dig example.com +tcp # confirm TCP/53 works
dig -x 93.184.216.34 # reverse lookup

Kubernetes DNS: The ndots:5 Trap

Pods get /etc/resolv.conf with several search domains and options ndots:5. A name with fewer than 5 dots is tried against each search suffix before being tried as an absolute name:

search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

So resolving api.example.com (2 dots) first queries api.example.com.default.svc.cluster.local, then ...svc.cluster.local, then ...cluster.local (each returning NXDOMAIN), and only then the real name, for both A and AAAA. One lookup becomes about 8 queries.

Mitigations:

  • Use a trailing dot (api.example.com.) for external hosts in hot paths.
  • Set dnsConfig.options: ndots: 2 per pod when most lookups are external.
  • Run NodeLocal DNSCache to cache on each node and upgrade the upstream hop to TCP.
  • Known failure mode: UDP DNS through conntrack can hit a race that drops packets and causes 5-second resolution stalls. Symptoms are random 5 s latency spikes. NodeLocal DNSCache is the standard fix.
  • Remember the JVM caches lookups too (see Java DNS Configuration above), so check both layers.

Dual-Stack: Happy Eyeballs

When a host has both A and AAAA records, clients using Happy Eyeballs (RFC 8305) start IPv6 first and, if it has not connected within about 250 ms, race an IPv4 attempt. A broken IPv6 path therefore costs about 250 ms, not a timeout, but only in clients that implement it. Plain socket code may still hang on a dead AAAA address.


Interview Questions

Q1. Describe the full DNS resolution process for api.example.com.

Client checks browser cache β†’ OS cache β†’ if miss, asks local resolver. Resolver checks its cache β†’ if miss, queries root NS for .com TLD NS β†’ queries TLD NS for example.com authoritative NS β†’ queries authoritative NS for api.example.com β†’ gets A record (IP + TTL). Resolver caches result and returns to client. Full chain: ~4 queries, 50–200ms. Cached: < 1ms.

Q2. What is a CNAME record and when can't you use it?

A CNAME aliases one hostname to another (the canonical name). The resolver follows the CNAME and looks up the final A/AAAA record. You cannot use CNAME at the zone apex (naked domain: example.com) because RFC 1034 forbids other records coexisting with a CNAME, and zones must have SOA/NS records. Use ALIAS or ANAME (Route 53, Cloudflare) for apex aliases β€” they resolve to A records.

Q3. What is DNS TTL and how does it affect deployments?

TTL is how long resolvers and clients cache a DNS answer. Low TTL (60s) allows fast IP changes but increases query load. Before changing IPs (failover, deployment), lower TTL to 60s and wait for the current TTL to expire globally. Then make the change. After traffic shifts, raise TTL again. Ignoring TTL is why "DNS propagation takes 24-48 hours" β€” high TTLs of existing records.

Q4. What is DNS cache poisoning and how does DNSSEC prevent it?

Cache poisoning: an attacker convinces a resolver to cache a fraudulent DNS mapping (e.g., bank.com β†’ attacker's IP). Classically exploited via Kaminsky attack by guessing the transaction ID. DNSSEC prevents this by signing zone data with cryptographic keys β€” the resolver validates the signature chain from the root. A tampered response has an invalid signature and is rejected.

Q5. What is the difference between a recursive resolver and an authoritative nameserver?

Recursive resolver (e.g., 8.8.8.8): accepts DNS queries from clients, does the work of traversing the hierarchy, caches results. It knows how to find answers but doesn't own any zones. Authoritative nameserver: owns the actual DNS records for a zone (example.com). It is the final source of truth and doesn't recurse β€” it just answers questions about its own zones.

Q6. What are SRV records and when are they used?

SRV (Service) records specify the hostname and port for a service: _service._proto.name TTL class SRV priority weight port target. Used by gRPC (for load balancing and discovery), SIP/VoIP, XMPP, and Kubernetes internal DNS. Example: _grpc._tcp.api.example.com SRV 10 20 443 api-grpc.example.com. Allows clients to discover service endpoints from DNS.

Q7. What is split-horizon DNS?

Split-horizon DNS returns different answers based on the requester's source IP. Internal clients get private IP addresses (routing traffic over the internal network), external clients get public IPs. Uses: keeping internal topology hidden, routing internal traffic without external NAT traversal, geographic load balancing. Implemented via DNS views in BIND or separate internal/external zones in cloud DNS.

Q8. Why might a Java application not respect a DNS TTL change immediately?

Java's JVM has its own DNS cache separate from the OS. By default it caches successful lookups indefinitely (networkaddress.cache.ttl=-1 in some older versions) or for 30 seconds. When DNS TTL expires, the OS and resolver update, but the JVM still serves the old cached IP. Fix: set networkaddress.cache.ttl in java.security or via Security.setProperty(). HTTP connection pools may also cache connections to specific IPs beyond the DNS TTL.

πŸ“–
Track Page Progress0 / 635 Read
Knowledge Base Completion0%