Computer Networks

The Application Layer

DNS

distributed by copying, until the mid-1980s.

JrCodex·8 min read

Jr Codex Computer Networks Notes

Level: Intermediate Prerequisites: Module 4, Chapter 5: TCP in the Real World Time to complete: ~25 minutes


Table of Contents

  1. The Problem DNS Solves
  2. The Hierarchy
  3. Resolving a Name
  4. Record Types
  5. Caching and TTL
  6. How DNS Fails
  7. Summary & Next Steps

1. The Problem DNS Solves

The Need
─────────────────────────────────────────
  Humans use names: example.com
  The network uses addresses: 93.184.216.34

  Something must translate, and it must:
    - scale to hundreds of millions of names
    - allow each organisation to manage its OWN
      names without central approval
    - answer in milliseconds
    - survive the failure of any part of itself
─────────────────────────────────────────
Why Not One Big File
─────────────────────────────────────────
  It genuinely was one file — HOSTS.TXT,
  distributed by copying, until the mid-1980s.

  It failed for the obvious reasons: every change
  required central coordination, the file grew
  without bound, and distribution could never keep
  up.

  DNS replaced it with a DISTRIBUTED, HIERARCHICAL,
  DELEGATED database — and every property above
  follows from those three words.
─────────────────────────────────────────

2. The Hierarchy

The Tree
─────────────────────────────────────────
                    . (root)
                      │
        ┌─────────────┼─────────────┐
       com           org            uk
        │             │              │
   ┌────┴────┐    wikipedia      ┌───┴───┐
 example  google                co      ac
    │                            │
  www, mail, api             bbc, gov
─────────────────────────────────────────
Reading a Name Correctly
─────────────────────────────────────────
  www.example.com.
  │   │       │  └ the ROOT (usually written
  │   │       │    implicitly)
  │   │       └── TOP-LEVEL DOMAIN
  │   └────────── SECOND-LEVEL DOMAIN
  └────────────── SUBDOMAIN

  Names are read RIGHT TO LEFT, most general to
  most specific — the same direction resolution
  proceeds.
─────────────────────────────────────────
DELEGATION — the key idea
─────────────────────────────────────────
  Each level delegates authority for the level
  below it.

  The root servers do not know about example.com.
  They know which servers handle .com, and say so.

  The .com servers do not know about
  www.example.com. They know which servers handle
  example.com.

  Only example.com's own nameservers know the
  answer.

  So NOBODY holds the whole database, and every
  organisation controls its own names without
  asking anyone. That is what makes DNS scale.
─────────────────────────────────────────
The Server Roles
─────────────────────────────────────────
  ROOT SERVERS       13 logical servers (a-m),
                     hundreds of physical
                     instances via anycast. They
                     know the TLD servers.

  TLD SERVERS        .com, .org, .uk. They know
                     which nameservers hold each
                     domain.

  AUTHORITATIVE      hold the ACTUAL RECORDS for a
                     domain. The source of truth.

  RECURSIVE RESOLVER Does the work on your behalf.
                     Your ISP's, or 8.8.8.8,
                     1.1.1.1. Caches heavily.
─────────────────────────────────────────

3. Resolving a Name

The Full Walk
─────────────────────────────────────────
  Your browser wants www.example.com.

  1. STUB RESOLVER (your OS) checks its cache, then
     asks the configured RECURSIVE RESOLVER.
     ── one query, and it waits for the answer

  2. RESOLVER asks a ROOT server.
     "Where is www.example.com?"
     ROOT: "I don't know, but .com is at
            a.gtld-servers.net" ── a REFERRAL

  3. RESOLVER asks the .com server.
     .com: "example.com is served by
            ns1.example.com" ── another referral

  4. RESOLVER asks ns1.example.com.
     ns1: "www.example.com is 93.184.216.34"
          ── an AUTHORITATIVE ANSWER

  5. RESOLVER caches it and returns it to you.
─────────────────────────────────────────
Two Kinds of Query
─────────────────────────────────────────
  RECURSIVE   "Get me the answer." The resolver
              does all the work and returns a final
              result.
              ── what your machine sends

  ITERATIVE   "Tell me what you know." The server
              returns a referral if it does not
              have the answer.
              ── what the resolver sends to root,
                 TLD and authoritative servers

  Root and TLD servers do NOT do recursion. If they
  did, thirteen server groups would be doing the
  work for the entire internet.
─────────────────────────────────────────
# Watch the full walk, referral by referral.
dig +trace www.example.com
 
# Ask one specific server, without recursion.
dig @8.8.8.8 example.com A
dig @a.root-servers.net com NS +norecurse
 
# What is actually cached, and for how long?
dig example.com A +noall +answer
# example.com.  3542  IN  A  93.184.216.34
#               └ seconds REMAINING on this cached entry

4. Record Types

The Ones That Matter
─────────────────────────────────────────
  A       name ──► IPv4 address
  AAAA    name ──► IPv6 address
  CNAME   name ──► ANOTHER NAME (an alias)
  MX      mail servers for this domain, with
          priority
  NS      the authoritative nameservers
  TXT     arbitrary text — used for SPF, DKIM,
          domain verification
  SOA     start of authority: the zone's primary
          server and timing parameters
  PTR     address ──► name (reverse DNS)
  SRV     service location: host, port, priority
  CAA     which certificate authorities may issue
          for this domain
─────────────────────────────────────────
THE CNAME RULES THAT CATCH PEOPLE
─────────────────────────────────────────
  1. A CNAME CANNOT COEXIST with any other record
     for the same name.

     So you CANNOT put a CNAME on the APEX
     (example.com), because the apex must have NS
     and SOA records.

     This is why "point my root domain at my CDN"
     is awkward, and why providers invented
     non-standard ALIAS or ANAME records to work
     around it.

  2. CNAME chains cost EXTRA LOOKUPS. Each hop is
     another query unless the server helpfully
     returns them together.

  3. An MX record must NOT point at a CNAME. It
     must name a host with an A or AAAA record.
─────────────────────────────────────────
dig example.com MX +short
dig example.com TXT +short          # SPF, verification tokens
dig -x 93.184.216.34 +short         # reverse lookup (PTR)
dig _sip._tcp.example.com SRV +short

5. Caching and TTL

Where Answers Are Cached
─────────────────────────────────────────
  1. the browser's own cache
  2. the operating system's stub resolver
  3. the recursive resolver (the big one)
  4. sometimes an intermediate forwarder

  Each entry carries a TTL — how many seconds it
  may be reused. It counts DOWN in the cache.
─────────────────────────────────────────
Choosing a TTL
─────────────────────────────────────────
  LONG (86400 = 1 day)
    + fewer queries, faster lookups, resilient if
      your nameservers go down
    - changes take up to a day to propagate

  SHORT (60-300 seconds)
    + fast failover and quick changes
    - more query load, and more sensitive to
      resolver latency

  THE MIGRATION PATTERN
    Days before a planned change, LOWER the TTL to
    60 seconds. Make the change. Confirm. Then
    RAISE it again.

    Do it in the wrong order and you are waiting a
    day for the old TTL to expire before your low
    TTL even takes effect.
─────────────────────────────────────────
NEGATIVE CACHING
─────────────────────────────────────────
  "This name does not exist" is ALSO cached,
  governed by the SOA record's minimum field.

  So creating a record that someone already queried
  and got NXDOMAIN for may not be visible for as
  long as that negative TTL.

  A frequent cause of "I created the record but it
  is not working" — and the answer is usually to
  wait rather than to change anything.
─────────────────────────────────────────

6. How DNS Fails

The Practical Failure Modes
─────────────────────────────────────────
  STALE CACHE
    You changed the record; something is still
    serving the old value. Check TTLs at every
    layer, including the application's own resolver
    cache.

  PROPAGATION CONFUSION
    DNS does not "propagate". Nothing is pushed.
    Different resolvers simply hold entries with
    different remaining TTLs. There is no
    broadcast to wait for.

  RESOLVER FAILURE
    If your configured resolver is down, EVERYTHING
    fails — and it looks like a total network
    outage, because no name resolves.
    This is why /etc/resolv.conf lists more than
    one.

  MISSING GLUE
    ns1.example.com is the nameserver FOR
    example.com. To find it you must resolve
    example.com. Circular.
    The parent zone must publish GLUE RECORDS — the
    nameserver's IP — to break the loop.

  DNS AMPLIFICATION
    A small spoofed query producing a large reply,
    aimed at a victim. Which is why open recursive
    resolvers should not exist on the public
    internet.
─────────────────────────────────────────
SECURITY: DNSSEC and ENCRYPTED TRANSPORT
─────────────────────────────────────────
  Plain DNS is UNAUTHENTICATED and UNENCRYPTED.
  Anyone on the path can observe or forge answers.

  DNSSEC signs records cryptographically, so a
  forged answer is detectable. It does NOT encrypt
  — everyone still sees what you looked up.

  DoT (DNS over TLS, port 853) and DoH (DNS over
  HTTPS, port 443) encrypt the query between you
  and your resolver. They provide PRIVACY from the
  network, not authenticity of the data. DNSSEC and
  DoH solve different problems, and both are worth
  having.
─────────────────────────────────────────
import socket, time
 
def resolve_all(hostname):
    """getaddrinfo is address-family agnostic — IPv4 and IPv6 (Module 3, Chapter 2)."""
    start = time.perf_counter()
    results = socket.getaddrinfo(hostname, None, socket.AF_UNSPEC, socket.SOCK_STREAM)
    elapsed = (time.perf_counter() - start) * 1000
 
    addrs = sorted({(r[0].name, r[4][0]) for r in results})
    print(f"{hostname}: {elapsed:.1f} ms")
    for family, addr in addrs:
        print(f"  {family:10} {addr}")
 
resolve_all("example.com")
# The FIRST call may take 30-100ms; the second is usually <1ms — the cache at work.

7. Summary & Next Steps

Key Takeaways

  • DNS scales because authority is delegated down a hierarchy, so nobody holds the whole database and every organisation manages its own names.
  • Your machine sends one recursive query; the resolver sends iterative queries and follows referrals from root to TLD to authoritative server.
  • A CNAME cannot coexist with other records, which is why it cannot be used on a domain apex — the source of much CDN configuration awkwardness.
  • DNS does not propagate; entries simply expire on their own TTLs, and lowering the TTL must be done before a planned change to be useful.

Concept Check

  1. Why do root and TLD servers answer only iterative queries?
  2. Why can you not put a CNAME on example.com itself?
  3. You created a DNS record an hour ago and it still returns NXDOMAIN from one resolver. What is the likely cause?

Next Chapter

Chapter 2: HTTP Fundamentals


Jr Codex — 1-on-1 Personalized Coaching | Back to Module Index | Back to Computer Networks Index