← Back to all projects

LEARN DNS

Every time you type a URL, send an email, or use almost any internet service, DNS is involved. It's the phone book of the internet, translating human-readable names (`google.com`) to machine-readable IP addresses (`142.250.80.46`). Yet most developers treat it as magic.

Learn DNS: Complete Mastery Through Projects

Goal: Deeply understand the Domain Name System from first principles - from basic lookups to building servers, implementing security, and mastering the distributed protocols that make the internet usable. By completing these projects, you will understand every byte in a DNS packet, know how queries travel from your computer to root servers and back, be able to troubleshoot any DNS issue, run your own DNS infrastructure, and understand DNS security threats and defenses.


Why DNS Matters

Every time you type a URL, send an email, or use almost any internet service, DNS is involved. It’s the phone book of the internet, translating human-readable names (google.com) to machine-readable IP addresses (142.250.80.46). Yet most developers treat it as magic.

DNS is not “a database of names.” It is a set of distributed protocols and conventions that enable the entire internet to function. Without DNS, we would need to memorize IP addresses for every website we visit. Understanding DNS deeply means understanding how the internet actually works at a fundamental level.

After completing these projects, you will:

  • Understand every byte in a DNS packet
  • Know how queries travel from your computer to root servers and back
  • Be able to troubleshoot any DNS issue
  • Run your own DNS infrastructure
  • Understand DNS security threats and defenses
  • Build tools that implement modern DNS privacy (DoH, DoT, DNSSEC)

Core Concept Analysis

The DNS Hierarchy

The DNS namespace forms a hierarchical tree structure, with the root at the top and domains branching downward:

                    . (root)
                    |
        +-----------+-----------+
        |           |           |
       com         org         net
        |           |           |
    +---+---+   example     cloudflare
    |       |       |           |
  google  amazon   www         www
    |       |
   www    mail

What You Must Truly Understand

To understand DNS end-to-end, you must internalize these core concepts:

1. The Namespace and Delegation Model

  • Root servers -> TLD servers -> zone cuts -> authoritative servers -> glue records and referrals
  • The DNS tree is stitched together through delegation - each zone points to its children

2. Zones vs. the Global Tree

  • A zone is a served slice of the namespace, not “a domain”
  • Zone cuts define administrative boundaries
  • Understanding zones is essential for running DNS infrastructure

3. DNS Message Format (RFC 1035) Every DNS query and response follows the same binary format:

  • Header (12 bytes): ID, flags, counts
  • Question section: What you’re asking
  • Answer section: The response records
  • Authority section: Who’s authoritative
  • Additional section: Helpful extras (including glue records)

4. Record Types Different types of DNS records serve different purposes:

  • A: IPv4 address
  • AAAA: IPv6 address
  • CNAME: Canonical name (alias)
  • MX: Mail exchanger
  • NS: Name server
  • TXT: Arbitrary text (used for SPF, DKIM, verification)
  • SOA: Start of Authority (zone metadata)
  • PTR: Pointer (reverse DNS)
  • SRV: Service location
  • DNSKEY/RRSIG/DS: DNSSEC records

5. Resolution Algorithm

  • Iterative walking: Following referrals from root to authoritative
  • CNAME/DNAME chaining: Following aliases
  • Referral handling: Processing NS records and glue
  • Recursive vs Iterative: Resolver does all the work vs client follows referrals

6. Transport Reality

  • UDP limits (512 bytes originally, extended via EDNS)
  • Truncation and TCP fallback
  • Retries and timeouts
  • EDNS(0) for modern capabilities

7. Caching Semantics

  • TTL: Time To Live and cache expiration
  • Cache keying: How records are stored and retrieved
  • Negative caching: Caching NXDOMAIN and NODATA responses
  • Bailiwick rules: Trust boundaries for cached data

8. Operational Failure Modes

  • SERVFAIL vs NXDOMAIN: Server failure vs non-existent domain
  • Lame delegations: NS records pointing to servers that don’t answer
  • Loops: CNAME chains that cycle
  • Timeouts: Network and server unavailability

9. Security and Privacy Layers

  • DNSSEC: Cryptographic signatures to verify authenticity (DNSKEY, RRSIG, DS, NSEC/NSEC3)
  • Anti-forgery mitigations: Transaction IDs, source port randomization
  • QNAME minimization: Sending only minimal info to each server
  • DoH (DNS over HTTPS): Encrypted DNS in HTTPS
  • DoT (DNS over TLS): Encrypted DNS in TLS

10. Change Propagation

  • Zone transfers (AXFR/IXFR): How secondary servers get zone data
  • Dynamic updates (RFC 2136): Programmatic DNS changes
  • TTL implications: How long changes take to propagate

Practical Tools

Essential tools for DNS work:

  • dig: The DNS Swiss Army knife
  • nslookup: Basic lookup tool
  • host: Simple DNS lookup
  • whois: Domain registration info

You learn these concepts best by building: a parser, a client, a server, a resolver, and then secure/privacy “overlays.”


Project 1: DNS Query Analyzer (Understand the Wire Format)

  • File: LEARN_DNS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: C, Go, Rust
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 1: Beginner
  • Knowledge Area: DNS Protocol / Binary Parsing
  • Software or Tool: Wireshark/tcpdump companion
  • Main Book: “TCP/IP Illustrated, Volume 1” by W. Richard Stevens

What you’ll build: A tool that captures DNS packets (or reads pcap files) and decodes them into human-readable format, showing every field: transaction ID, flags, questions, answers, and all record data.

Why it teaches DNS: Before you can build DNS tools, you need to see DNS. This project forces you to understand the binary wire format—every byte has meaning. After this, DNS packets will never be mysterious again.

Core challenges you’ll face:

  • Parsing the 12-byte DNS header → maps to understanding flags, opcodes, and counts
  • Decoding domain name compression → maps to the pointer mechanism (0xC0)
  • Handling different record types → maps to RDATA format varies by type
  • Distinguishing queries from responses → maps to QR flag and structure differences

Key Concepts:

  • DNS Message Format: RFC 1035 Section 4
  • Domain Name Encoding: “DNS and BIND” Chapter 15 - Albitz & Liu
  • Binary Parsing in Python: “Black Hat Python” Chapter 3 - Justin Seitz
  • Name Compression: RFC 1035 Section 4.1.4

Difficulty: Beginner Time estimate: Weekend Prerequisites: Basic Python, understanding of binary/hex

Real world outcome:

$ sudo ./dns_analyzer eth0
Capturing DNS packets on eth0...

[Query] ID:0x1234 Flags:0x0100 (RD)
  Question: www.google.com. A IN

[Response] ID:0x1234 Flags:0x8180 (QR RD RA)
  Question: www.google.com. A IN
  Answer: www.google.com. 300 IN A 142.250.80.46
  Answer: www.google.com. 300 IN A 142.250.80.47

[Query] ID:0x5678 Flags:0x0100 (RD)
  Question: mail.example.com. MX IN

[Response] ID:0x5678 Flags:0x8180 (QR RD RA)
  Question: mail.example.com. MX IN
  Answer: mail.example.com. 3600 IN MX 10 mail1.example.com.
  Answer: mail.example.com. 3600 IN MX 20 mail2.example.com.
  Additional: mail1.example.com. 3600 IN A 192.0.2.1

Implementation Hints:

DNS header structure (12 bytes):

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                      ID                       | 2 bytes
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   | 2 bytes (flags)
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    QDCOUNT                    | 2 bytes
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    ANCOUNT                    | 2 bytes
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    NSCOUNT                    | 2 bytes
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    ARCOUNT                    | 2 bytes
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Pseudo-code approach:

1. Capture UDP packets on port 53 (or read from pcap)
2. Parse DNS header:
   - ID (2 bytes, big-endian)
   - Flags (2 bytes, decode each bit)
   - Counts for each section
3. Parse Question section:
   - Domain name (length-prefixed labels)
   - Type (2 bytes)
   - Class (2 bytes)
4. Parse Answer/Authority/Additional sections:
   - Domain name (may be compressed with pointer)
   - Type, Class, TTL, RDLENGTH
   - RDATA (format depends on Type)
5. Pretty-print everything

Domain name compression: If the first two bits of a label are 11, the remaining 14 bits are an offset into the message where the rest of the name is found.

Learning milestones:

  1. You parse the header correctly → You understand the DNS message structure
  2. You decode domain names → You understand label encoding
  3. You handle compression pointers → You understand DNS optimization
  4. You parse multiple record types → You understand RDATA formats

Project 2: Build Your Own dig Clone

  • File: LEARN_DNS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: C, Go, Rust
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: DNS Client / UDP Sockets
  • Software or Tool: dig utility clone
  • Main Book: “DNS and BIND” by Paul Albitz & Cricket Liu

What you’ll build: A command-line DNS lookup tool that queries DNS servers directly, displays results in dig-like format, and supports different record types, custom servers, and debug output.

Why it teaches DNS: dig is the essential DNS debugging tool. Building your own means you understand how to construct queries, send them via UDP, and parse responses. This is the client side of DNS.

Core challenges you’ll face:

  • Constructing valid DNS queries → maps to encoding domain names and setting flags
  • Handling UDP communication → maps to socket programming basics
  • Parsing all common record types → maps to A, AAAA, CNAME, MX, NS, TXT, SOA
  • Following CNAME chains → maps to understanding aliases
  • Timeout and retry logic → maps to network reliability

Key Concepts:

  • DNS Query Construction: RFC 1035 Section 4.1
  • Record Type Formats: RFC 1035 Sections 3.3 and 3.4
  • UDP DNS Limits: RFC 1035 Section 2.3.4 (512 byte limit, now extended)
  • EDNS0: RFC 6891 (larger UDP payloads)

Resources for key challenges:

Difficulty: Intermediate Time estimate: 1 week Prerequisites: Project 1 (DNS Analyzer)

Real world outcome:

$ ./mydig google.com
; <<>> MyDig 1.0 <<>> google.com
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12345
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;google.com.                    IN      A

;; ANSWER SECTION:
google.com.             299     IN      A       142.250.80.46
google.com.             299     IN      A       142.250.80.47
google.com.             299     IN      A       142.250.80.78

;; Query time: 14 msec
;; SERVER: 8.8.8.8#53
;; WHEN: Fri Dec 20 10:30:00 2025
;; MSG SIZE  rcvd: 124

$ ./mydig -t MX gmail.com @1.1.1.1
; <<>> MyDig 1.0 <<>> -t MX gmail.com @1.1.1.1
;; ANSWER SECTION:
gmail.com.              3600    IN      MX      5 gmail-smtp-in.l.google.com.
gmail.com.              3600    IN      MX      10 alt1.gmail-smtp-in.l.google.com.

$ ./mydig -t TXT _dmarc.google.com
;; ANSWER SECTION:
_dmarc.google.com.      300     IN      TXT     "v=DMARC1; p=reject; ..."

Implementation Hints:

Pseudo-code approach:

1. Parse command line: domain, type, server
2. Build DNS query:
   a. Generate random 16-bit ID
   b. Set flags: RD=1 (recursion desired)
   c. QDCOUNT=1
   d. Encode domain name as labels
   e. Add QTYPE and QCLASS
3. Create UDP socket
4. Send query to server:53
5. Receive response (with timeout)
6. Parse response using Project 1 logic
7. Format output like dig

Query building in detail:

def build_query(domain, record_type):
    header = struct.pack(">HHHHHH",
        random_id(),      # ID
        0x0100,           # Flags: RD=1
        1,                # QDCOUNT
        0, 0, 0           # AN, NS, AR counts
    )
    question = encode_domain(domain) + struct.pack(">HH", record_type, 1)
    return header + question

def encode_domain(domain):
    result = b""
    for label in domain.split("."):
        result += bytes([len(label)]) + label.encode()
    return result + b"\x00"  # null terminator

Learning milestones:

  1. Simple A record queries work → You can construct and parse DNS messages
  2. Multiple record types work → You understand RDATA formats
  3. Custom DNS servers work → You understand the resolver selection
  4. CNAME chains resolve → You understand aliases

Project 3: Recursive DNS Resolver (From Root Servers)

  • File: LEARN_DNS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: C, Go, Rust
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: DNS Resolution / Hierarchy
  • Software or Tool: Recursive resolver
  • Main Book: “DNS and BIND” by Paul Albitz & Cricket Liu

What you’ll build: A DNS resolver that performs full recursive resolution starting from root servers—following the chain of referrals through TLD servers to authoritative servers, just like a real recursive resolver does.

Why it teaches DNS: This is where you truly understand the DNS hierarchy. You’ll see that google.com isn’t resolved in one step—it requires asking root servers about .com, then .com servers about google.com, then Google’s servers for the final answer. This is the heart of how DNS works.

Core challenges you’ll face:

  • Knowing the root server addresses → maps to root hints file
  • Following NS referrals → maps to iterative resolution
  • Handling glue records → maps to why additional section exists
  • Detecting and handling loops → maps to CNAME chains and delegation loops
  • Caching intermediate results → maps to performance optimization

Key Concepts:

  • Recursive Resolution: “DNS and BIND” Chapter 2 - Albitz & Liu
  • Root Servers: IANA Root Servers
  • Glue Records: “DNS and BIND” Chapter 4 - Albitz & Liu
  • Referral Processing: RFC 1034 Section 5.3

Resources for key challenges:

Difficulty: Advanced Time estimate: 1-2 weeks Prerequisites: Project 2 (dig clone)

Real world outcome:

$ ./myresolver --trace www.example.com
Starting resolution for www.example.com...

[1] Querying root server a.root-servers.net (198.41.0.4)
    Response: Referral to .com TLD servers
    Got NS: a.gtld-servers.net, b.gtld-servers.net, ...
    Got glue: a.gtld-servers.net -> 192.5.6.30

[2] Querying TLD server a.gtld-servers.net (192.5.6.30)
    Response: Referral to example.com authoritative servers
    Got NS: a.iana-servers.net, b.iana-servers.net
    Got glue: a.iana-servers.net -> 199.43.135.53

[3] Querying authoritative server a.iana-servers.net (199.43.135.53)
    Response: ANSWER
    www.example.com. 86400 IN A 93.184.216.34

Resolution complete: www.example.com = 93.184.216.34
Total queries: 3

Implementation Hints:

The resolution algorithm (simplified):

def resolve(domain, record_type):
    # Start with root servers
    nameservers = ROOT_SERVERS

    while True:
        # Query one of the nameservers
        response = query(random.choice(nameservers), domain, record_type)

        if response.has_answer():
            # We found it!
            return response.answer_records()

        if response.has_authority():
            # We got a referral, follow it
            # Get new nameserver IPs from additional section (glue)
            # or resolve NS names if no glue
            nameservers = get_nameserver_ips(response)
        else:
            # No answer and no referral - NXDOMAIN or error
            return None

Root servers (you need to bootstrap with these):

ROOT_SERVERS = [
    ("a.root-servers.net", "198.41.0.4"),
    ("b.root-servers.net", "199.9.14.201"),
    ("c.root-servers.net", "192.33.4.12"),
    # ... more
]

Tricky cases:

  • No glue records: Sometimes NS records point to names in different zones. You need to recursively resolve the NS name first.
  • CNAME at answer: If you’re looking for A but find CNAME, follow the CNAME target.

Learning milestones:

  1. You reach root servers → You understand the starting point
  2. You follow referrals correctly → You understand DNS delegation
  3. You handle missing glue → You understand the chicken-and-egg problem
  4. You resolve any domain → You’ve implemented a real resolver

Project 4: Authoritative DNS Server

  • File: LEARN_DNS.md
  • Main Programming Language: C
  • Alternative Programming Languages: Python, Go, Rust
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: DNS Server / Zone Management
  • Software or Tool: BIND/NSD clone
  • Main Book: “DNS and BIND” by Paul Albitz & Cricket Liu

What you’ll build: A DNS server that answers authoritatively for zones you configure—reading zone files, responding to queries with proper authority, and handling zone transfers.

Why it teaches DNS: Being the authoritative source for a domain means understanding zones, SOA records, NS delegation, and what it means to be the “source of truth” for DNS data. This is what Cloudflare, Route53, and every DNS host runs.

Core challenges you’ll face:

  • Parsing zone files → maps to BIND zone file format
  • Responding with authority → maps to AA flag and NS records
  • SOA record management → maps to serial numbers, refresh, retry
  • Handling zone transfers (AXFR) → maps to TCP DNS and zone replication
  • NXDOMAIN vs NODATA → maps to proper negative responses

Key Concepts:

  • Zone File Format: “DNS and BIND” Chapter 4 - Albitz & Liu
  • SOA Record: RFC 1035 Section 3.3.13
  • Zone Transfers: RFC 5936 (AXFR)
  • Authoritative Responses: RFC 1035 Section 4.1.1 (AA flag)

Difficulty: Advanced Time estimate: 2-3 weeks Prerequisites: Projects 1-3

Real world outcome:

$ cat zones/mylab.local.zone
$TTL 86400
@       IN      SOA     ns1.mylab.local. admin.mylab.local. (
                        2024010101  ; Serial
                        3600        ; Refresh
                        1800        ; Retry
                        604800      ; Expire
                        86400 )     ; Minimum TTL
        IN      NS      ns1.mylab.local.
        IN      NS      ns2.mylab.local.
ns1     IN      A       192.168.1.10
ns2     IN      A       192.168.1.11
www     IN      A       192.168.1.20
mail    IN      A       192.168.1.30
        IN      MX      10 mail.mylab.local.
api     IN      CNAME   www.mylab.local.

$ ./mydns-auth --zone zones/
Authoritative DNS Server starting...
Loaded zone: mylab.local (8 records)
Listening on port 53

# Test it:
$ dig @localhost www.mylab.local
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 2
;; ANSWER SECTION:
www.mylab.local.        86400   IN      A       192.168.1.20
;; AUTHORITY SECTION:
mylab.local.            86400   IN      NS      ns1.mylab.local.
mylab.local.            86400   IN      NS      ns2.mylab.local.

$ dig @localhost nonexistent.mylab.local
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 1
;; AUTHORITY SECTION:
mylab.local.            86400   IN      SOA     ns1.mylab.local. admin.mylab.local. ...
;; ->>HEADER<<- ... status: NXDOMAIN

Implementation Hints:

Zone file parsing requires handling:

  • TTL directives ($TTL)
  • Origin directives ($ORIGIN)
  • @ as shorthand for zone name
  • Relative vs absolute names (trailing dot)
  • Multi-line records (parentheses)

Pseudo-code approach:

1. Load zone files into memory
   - For each zone: {name -> {type -> [records]}}
2. Listen on UDP port 53
3. For each query:
   a. Find matching zone (longest suffix match)
   b. If no zone matches:
      - Return REFUSED or forward (if configured)
   c. Look up exact name in zone
   d. If found:
      - Build response with answers
      - Set AA flag (authoritative answer)
      - Include NS records in authority section
   e. If not found but zone exists:
      - Return NXDOMAIN with SOA in authority
   f. Handle special cases:
      - Wildcards (*.example.com)
      - CNAME (return CNAME, maybe follow it)

Learning milestones:

  1. You serve records from zone files → You understand zone configuration
  2. The AA flag is set correctly → You understand authoritative responses
  3. NXDOMAIN returns SOA → You understand negative caching
  4. Wildcard records work → You understand advanced zone features

Project 5: DNS Caching Resolver

  • File: LEARN_DNS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Rust, C
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: DNS Caching / TTL Management
  • Software or Tool: Unbound/dnsmasq clone
  • Main Book: “DNS and BIND” by Paul Albitz & Cricket Liu

What you’ll build: A caching DNS resolver that serves your local network, caching responses to reduce upstream queries, respecting TTLs, and providing fast local DNS resolution.

Why it teaches DNS: Caching is what makes DNS scalable. Without caching, every DNS query would need to traverse the entire hierarchy. Understanding TTLs, cache eviction, and negative caching is essential for DNS performance tuning.

Core challenges you’ll face:

  • Implementing a TTL-aware cache → maps to expiration and refresh
  • Negative caching (NXDOMAIN) → maps to SOA minimum TTL
  • Cache size management → maps to eviction policies
  • Concurrent query handling → maps to async/threading
  • Upstream server selection → maps to failover and load balancing

Key Concepts:

  • DNS Caching: “DNS and BIND” Chapter 5 - Albitz & Liu
  • Negative Caching: RFC 2308
  • TTL Handling: RFC 1035 Section 4.1.3
  • Cache Poisoning Prevention: RFC 5452

Difficulty: Advanced Time estimate: 2 weeks Prerequisites: Projects 2-3

Real world outcome:

$ ./mycache --upstream 8.8.8.8,1.1.1.1 --port 53
Caching DNS Resolver starting...
Upstream servers: 8.8.8.8, 1.1.1.1
Listening on port 53

# First query - cache miss:
$ dig @localhost google.com
;; Query time: 45 msec
;; SERVER: 127.0.0.1#53

# Second query - cache hit:
$ dig @localhost google.com
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53

# Server log:
[MISS] google.com A -> forwarded to 8.8.8.8 (45ms)
[CACHE] google.com A TTL=300
[HIT] google.com A -> cached (TTL remaining: 298s)

# Stats command:
$ ./mycache --stats
Cache Statistics:
  Entries: 1,234
  Hits: 15,678 (87%)
  Misses: 2,345 (13%)
  Memory: 2.3 MB
  Oldest entry: 298s remaining

Top cached domains:
  google.com          (hits: 234, TTL: 156s)
  facebook.com        (hits: 189, TTL: 45s)
  cdn.example.com     (hits: 156, TTL: 3421s)

Implementation Hints:

Cache structure:

cache = {
    (domain, record_type): {
        "records": [...],
        "expires_at": timestamp,
        "inserted_at": timestamp
    }
}

Pseudo-code approach:

1. Start with upstream server list
2. Listen on port 53
3. For each query:
   a. Check cache for (domain, type)
   b. If cached and not expired:
      - Return cached records
      - Decrement TTL by time since caching
   c. If not cached or expired:
      - Forward to upstream (with failover)
      - Cache response with TTL
      - Return to client
4. Background thread: evict expired entries

Negative caching:

  • When you get NXDOMAIN, cache it too
  • TTL comes from SOA minimum field
  • This prevents repeated queries for non-existent domains

Learning milestones:

  1. Cache hits work → You understand basic caching
  2. TTL countdown is correct → You understand TTL semantics
  3. Expired entries are evicted → You understand cache management
  4. NXDOMAIN is cached → You understand negative caching

Project 6: DNS Sinkhole / Ad Blocker (Pi-hole Clone)

  • File: LEARN_DNS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Rust
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: DNS Filtering / Blocklists
  • Software or Tool: Pi-hole clone
  • Main Book: “DNS and BIND” by Paul Albitz & Cricket Liu

What you’ll build: A DNS-based ad blocker that intercepts DNS queries, blocks domains on a blocklist by returning 0.0.0.0, and forwards legitimate queries—providing network-wide ad blocking for all devices.

Why it teaches DNS: This shows DNS as a control point. By owning DNS resolution, you control what domains can be accessed. You’ll understand why Pi-hole works, how corporate DNS filtering operates, and the power of DNS in network security.

Core challenges you’ll face:

  • Efficient blocklist lookup → maps to data structures (sets, tries)
  • Wildcard matching → maps to pattern matching for subdomains
  • Crafting sinkhole responses → maps to synthesizing DNS responses
  • Logging and statistics → maps to observability
  • Allowlist overrides → maps to exception handling

Key Concepts:

  • DNS Sinkhole: Pi-hole Documentation
  • Blocklist Formats: Various (hosts file, domain list, regex)
  • Synthesized Responses: Crafting fake DNS responses
  • Query Logging: For statistics and debugging

Resources for key challenges:

Difficulty: Advanced Time estimate: 2 weeks Prerequisites: Project 5 (Caching Resolver)

Real world outcome:

$ ./mysinkhole --blocklist lists/ --upstream 8.8.8.8
DNS Sinkhole starting...
Loaded 150,000 domains from 5 blocklists
Listening on port 53

# From any device (configure this as DNS):
$ curl -I ads.doubleclick.net
# Connection refused - domain blocked!

$ curl google.com
# Works normally

# Server log:
[BLOCK] ads.doubleclick.net A -> 0.0.0.0 (list: easylist)
[BLOCK] tracker.facebook.com A -> 0.0.0.0 (list: privacy)
[ALLOW] google.com A -> 8.8.8.8 -> 142.250.80.46

# Dashboard:
$ ./mysinkhole --stats
Today's Statistics:
  Total queries:      12,345
  Blocked:            4,567 (37%)
  Forwarded:          7,778 (63%)

Top Blocked:
  1. ads.google.com             (567 blocks)
  2. tracker.facebook.com       (432 blocks)
  3. pixel.quantserve.com       (321 blocks)

Top Allowed:
  1. google.com                 (234 queries)
  2. api.github.com             (189 queries)

Implementation Hints:

Blocklist handling:

def load_blocklists(directory):
    blocked = set()
    for file in os.listdir(directory):
        for line in open(file):
            line = line.strip()
            if line and not line.startswith('#'):
                # Handle different formats:
                # 0.0.0.0 ads.example.com  (hosts file)
                # ads.example.com          (domain list)
                # ||ads.example.com^       (adblock format)
                domain = parse_domain(line)
                blocked.add(domain)
    return blocked

Pseudo-code for sinkhole:

1. Load blocklists into a set
2. Listen on port 53
3. For each query:
   a. Extract domain from question
   b. Check if domain or any parent is blocked:
      - "ads.tracking.example.com" checks:
        - ads.tracking.example.com
        - tracking.example.com
        - example.com
   c. If blocked:
      - Build response with A record = 0.0.0.0
      - Log the block
   d. If allowed:
      - Forward to upstream
      - Cache and return response
4. Maintain statistics

Learning milestones:

  1. One domain is blocked → You understand the sinkhole concept
  2. Real blocklists load → You understand list formats
  3. Ads disappear from browsers → You’re running network-wide blocking
  4. Stats show blocked percentage → You understand query analysis

Project 7: Reverse DNS Lookup Tool

  • File: LEARN_DNS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: C, Go
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: PTR Records / in-addr.arpa
  • Software or Tool: Reverse DNS tool
  • Main Book: “DNS and BIND” by Paul Albitz & Cricket Liu

What you’ll build: A tool that performs reverse DNS lookups—given an IP address, find the associated hostname. Also: a reverse zone generator for your network.

Why it teaches DNS: Reverse DNS uses the same protocol but inverts the lookup. Understanding in-addr.arpa and PTR records shows DNS’s flexibility. Reverse DNS is essential for mail servers, security logging, and network documentation.

Core challenges you’ll face:

  • Constructing in-addr.arpa queries → maps to IP address reversal
  • Handling classless delegation → maps to CIDR and RFC 2317
  • IPv6 reverse DNS (ip6.arpa) → maps to nibble format
  • Bulk reverse lookups → maps to performance optimization

Key Concepts:

  • Reverse DNS: “DNS and BIND” Chapter 4 - Albitz & Liu
  • in-addr.arpa Zone: RFC 1035 Section 3.5
  • IPv6 Reverse: RFC 3596
  • Classless Reverse: RFC 2317

Difficulty: Intermediate Time estimate: 1 week Prerequisites: Project 2 (dig clone)

Real world outcome:

$ ./myreversedns 8.8.8.8
8.8.8.8 -> dns.google

$ ./myreversedns 1.1.1.1
1.1.1.1 -> one.one.one.one

$ ./myreversedns 192.168.1.1
192.168.1.1 -> (no PTR record)

# Bulk reverse lookup:
$ ./myreversedns --range 8.8.8.0/24 | head
8.8.8.8 -> dns.google
8.8.8.4 -> dns.google
...

# IPv6:
$ ./myreversedns 2001:4860:4860::8888
2001:4860:4860::8888 -> dns.google

# Generate reverse zone file:
$ ./myreversedns --generate-zone 192.168.1.0/24 > 1.168.192.in-addr.arpa.zone

Implementation Hints:

To look up 192.168.1.100, you query for: 100.1.168.192.in-addr.arpa PTR

Pseudo-code approach:

def reverse_lookup(ip):
    if is_ipv4(ip):
        # Reverse octets
        reversed_ip = ".".join(ip.split(".")[::-1])
        query_name = f"{reversed_ip}.in-addr.arpa"
    else:  # IPv6
        # Expand to full form, reverse nibbles
        expanded = expand_ipv6(ip)
        nibbles = expanded.replace(":", "")
        reversed_nibbles = ".".join(reversed(nibbles))
        query_name = f"{reversed_nibbles}.ip6.arpa"

    response = dns_query(query_name, "PTR")
    return response.answer[0].target if response.answer else None

Learning milestones:

  1. IPv4 reverse lookups work → You understand in-addr.arpa
  2. IPv6 reverse lookups work → You understand ip6.arpa nibble format
  3. You generate reverse zone files → You can manage reverse DNS

Project 8: DNS-over-HTTPS (DoH) Client

  • File: LEARN_DNS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Rust
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: DNS Security / HTTPS
  • Software or Tool: DoH client
  • Main Book: “Serious Cryptography” by Jean-Philippe Aumasson

What you’ll build: A DNS client that sends queries encrypted via HTTPS to DoH servers (Cloudflare’s 1.1.1.1, Google’s 8.8.8.8), preventing ISP snooping on your DNS traffic.

Why it teaches DNS: Traditional DNS is unencrypted—anyone on the network can see what domains you’re looking up. DoH wraps DNS in HTTPS, providing privacy. Understanding DoH means understanding modern DNS privacy.

Core challenges you’ll face:

  • HTTP/2 or HTTP/1.1 over HTTPS → maps to HTTP client programming
  • DNS wire format in HTTP body → maps to content-type: application/dns-message
  • Parsing DoH responses → maps to same wire format as UDP
  • Certificate validation → maps to TLS security

Key Concepts:

  • DoH Specification: RFC 8484
  • DoH Endpoints: Cloudflare DoH
  • HTTP POST for DNS: RFC 8484 Section 4.1
  • TLS/HTTPS: Basic understanding of encrypted connections

Difficulty: Intermediate Time estimate: 1 week Prerequisites: Project 2, basic HTTPS understanding

Real world outcome:

$ ./mydoh google.com
Using DoH server: https://cloudflare-dns.com/dns-query
Query encrypted via HTTPS

;; ANSWER SECTION:
google.com.             252     IN      A       142.250.80.46

$ ./mydoh --server https://dns.google/dns-query example.com
Using DoH server: https://dns.google/dns-query

;; ANSWER SECTION:
example.com.            86400   IN      A       93.184.216.34

# Compare timing:
$ ./mydoh --benchmark google.com
Traditional DNS (8.8.8.8):        14ms
DoH (cloudflare-dns.com):         45ms
DoH (dns.google):                 52ms

Implementation Hints:

DoH uses the same wire format as UDP DNS, just wrapped in HTTPS:

import requests
import base64

def doh_query(domain, record_type="A", server="https://cloudflare-dns.com/dns-query"):
    # Build DNS query (same as UDP)
    query = build_dns_query(domain, record_type)

    # Option 1: POST with binary body
    response = requests.post(
        server,
        data=query,
        headers={"Content-Type": "application/dns-message"}
    )

    # Option 2: GET with base64url-encoded query
    # encoded = base64.urlsafe_b64encode(query).rstrip(b'=').decode()
    # response = requests.get(f"{server}?dns={encoded}")

    # Parse response (same format as UDP DNS)
    return parse_dns_response(response.content)

Learning milestones:

  1. You make a DoH query → You understand DNS over HTTPS
  2. Binary DNS in HTTP works → You understand the transport layer change
  3. Privacy is achieved → You understand why DoH matters
  4. You compare with plain DNS → You understand the latency tradeoff

Project 9: DNS-over-TLS (DoT) Client

  • File: LEARN_DNS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Rust, C
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: DNS Security / TLS
  • Software or Tool: DoT client
  • Main Book: “Serious Cryptography” by Jean-Philippe Aumasson

What you’ll build: A DNS client that connects to DoT servers over TLS on port 853, encrypting DNS queries at the transport layer—an alternative to DoH.

Why it teaches DNS: DoT is simpler than DoH (just TLS over TCP, not HTTP over TLS over TCP) but achieves the same privacy goal. Understanding both helps you compare approaches and understand the DNS privacy landscape.

Core challenges you’ll face:

  • TLS connection establishment → maps to TLS handshake
  • TCP DNS framing → maps to 2-byte length prefix
  • Certificate validation → maps to TLS security
  • Connection reuse → maps to persistent connections

Key Concepts:

  • DoT Specification: RFC 7858
  • TCP DNS Framing: RFC 1035 Section 4.2.2
  • TLS 1.3: RFC 8446 (modern TLS)
  • Port 853: The designated DoT port

Difficulty: Intermediate Time estimate: 1 week Prerequisites: Project 2, basic TLS understanding

Real world outcome:

$ ./mydot google.com
Connecting to 1.1.1.1:853 over TLS...
TLS 1.3 established with cloudflare-dns.com

;; ANSWER SECTION:
google.com.             299     IN      A       142.250.80.46

$ ./mydot --server 8.8.8.8 --verify example.com
Connecting to 8.8.8.8:853 over TLS...
Certificate verified: dns.google
TLS 1.3 established

;; ANSWER SECTION:
example.com.            86400   IN      A       93.184.216.34

Implementation Hints:

TCP DNS adds a 2-byte length prefix:

import ssl
import socket

def dot_query(domain, record_type="A", server="1.1.1.1"):
    # Build DNS query (same as UDP)
    query = build_dns_query(domain, record_type)

    # Create TLS connection
    context = ssl.create_default_context()
    sock = socket.create_connection((server, 853))
    tls_sock = context.wrap_socket(sock, server_hostname="cloudflare-dns.com")

    # TCP DNS: prepend 2-byte length
    length = struct.pack(">H", len(query))
    tls_sock.send(length + query)

    # Read response: first 2 bytes are length
    response_length = struct.unpack(">H", tls_sock.recv(2))[0]
    response = tls_sock.recv(response_length)

    tls_sock.close()
    return parse_dns_response(response)

Learning milestones:

  1. TLS connection works → You understand encrypted transport
  2. TCP framing works → You understand DNS over TCP
  3. Queries resolve → You’ve implemented DoT
  4. You compare with DoH → You understand the tradeoffs

Project 10: Local DNS Proxy with Encryption

  • File: LEARN_DNS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Rust
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: DNS Privacy / Proxy
  • Software or Tool: dnscrypt-proxy clone
  • Main Book: “Serious Cryptography” by Jean-Philippe Aumasson

What you’ll build: A local DNS proxy that accepts traditional DNS queries on port 53 and forwards them encrypted via DoH or DoT to upstream servers—providing DNS privacy for your entire network.

Why it teaches DNS: This combines caching, forwarding, and encryption. You’ll see how tools like dnscrypt-proxy work, and understand how to add privacy to legacy DNS clients that don’t support DoH/DoT natively.

Core challenges you’ll face:

  • UDP to HTTPS/TLS translation → maps to protocol bridging
  • Connection pooling for efficiency → maps to performance optimization
  • Fallback between DoH and DoT → maps to resilience
  • Caching to reduce latency → maps to encrypted DNS is slower
  • Bootstrap problem → maps to resolving DoH server names

Key Concepts:

  • DNS Proxy Design: Combining previous projects
  • Connection Reuse: HTTP/2 or persistent TLS
  • Latency Hiding: Caching and prefetching
  • Bootstrap: Using IP addresses to avoid chicken-and-egg

Difficulty: Advanced Time estimate: 2 weeks Prerequisites: Projects 5, 8, 9

Real world outcome:

$ ./myproxy --upstream-doh https://cloudflare-dns.com/dns-query \
            --upstream-dot 1.1.1.1 --port 53
DNS Privacy Proxy starting...
Listening on port 53 (UDP)
Upstream (DoH): cloudflare-dns.com
Upstream (DoT): 1.1.1.1 (fallback)

# Configure any device to use localhost as DNS:
$ dig @localhost google.com
;; Query time: 48 msec (first query, DoH)

$ dig @localhost google.com
;; Query time: 0 msec (cached)

# Log output:
[RECV] google.com A from 127.0.0.1
[DoH] -> cloudflare-dns.com (48ms)
[CACHE] google.com A TTL=299
[RECV] google.com A from 127.0.0.1
[HIT] google.com A (cached)

# Stats:
Queries:      1,234
Cache hits:   890 (72%)
DoH queries:  300
DoT queries:  44 (fallback)
Avg latency:  12ms

Implementation Hints:

Architecture:

+---------+     +-------------+     +------------------+
| Clients |---->| Local Proxy |---->| DoH/DoT Upstream |
| (UDP)   |     | (UDP+Cache) |     | (Encrypted)      |
+---------+     +-------------+     +------------------+
                      |
                  [Cache]

Pseudo-code:

1. Start UDP listener on port 53
2. Initialize connection pool for DoH (HTTP/2) and DoT
3. For each query:
   a. Check cache
   b. If miss:
      - Try DoH first (faster for HTTP/2 multiplexing)
      - Fallback to DoT if DoH fails
      - Cache response
   c. Return response via UDP

Bootstrap: Use IP addresses in config (not hostnames) to avoid needing DNS to find DNS.

Learning milestones:

  1. Proxy translates UDP to DoH → You understand protocol bridging
  2. Caching hides latency → You understand performance tradeoffs
  3. Fallback works → You understand resilience
  4. Network-wide privacy achieved → You’ve built a real privacy tool

Project 11: DNSSEC Validator

  • File: LEARN_DNS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Rust
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 4: Expert
  • Knowledge Area: DNSSEC / Cryptographic Validation
  • Software or Tool: DNSSEC validator
  • Main Book: “Serious Cryptography” by Jean-Philippe Aumasson

What you’ll build: A DNS resolver that validates DNSSEC signatures, verifying the cryptographic chain of trust from root servers to the domain you’re looking up—proving the response is authentic.

Why it teaches DNS: DNSSEC is how DNS becomes secure against spoofing. Understanding it requires cryptography knowledge and appreciation for the chain of trust. After building this, you’ll understand why DNSSEC adoption matters.

Core challenges you’ll face:

  • Understanding DNSSEC record types → maps to RRSIG, DNSKEY, DS, NSEC/NSEC3
  • Validating RSA/ECDSA signatures → maps to cryptographic verification
  • Building the chain of trust → maps to DS to DNSKEY linkage
  • Handling negative proofs (NSEC) → maps to authenticated denial of existence
  • Key rollover → maps to DNSKEY algorithm and timing

Key Concepts:

  • DNSSEC Overview: Cloudflare - How DNSSEC Works
  • DNSSEC RFCs: RFC 4033, 4034, 4035
  • DNSKEY and RRSIG: RFC 4034 Sections 2 and 3
  • Chain of Trust: RFC 4035 Section 5

Resources for key challenges:

Difficulty: Expert Time estimate: 3-4 weeks Prerequisites: Projects 3-4, cryptography basics

Real world outcome:

$ ./mydnssec cloudflare.com
Resolving cloudflare.com with DNSSEC validation...

[1] Query: cloudflare.com DNSKEY
    Got 2 DNSKEY records (KSK and ZSK)
    Verifying DNSKEY RRSIG with DS from parent (.com)... ✓

[2] Query: cloudflare.com A + RRSIG
    Got A records: 104.16.132.229, 104.16.133.229
    Verifying A record RRSIG with cloudflare.com DNSKEY... ✓

Chain of Trust:
  . (root) -> DS -> .com DNSKEY ✓
  .com -> DS -> cloudflare.com DNSKEY ✓
  cloudflare.com DNSKEY -> RRSIG -> A records ✓

RESULT: cloudflare.com = 104.16.132.229 (SECURE)

$ ./mydnssec example-not-signed.com
Resolving example-not-signed.com with DNSSEC validation...
No DNSKEY found, zone is not signed.
RESULT: example-not-signed.com = x.x.x.x (INSECURE)

$ ./mydnssec spoofed.example.com
Resolving spoofed.example.com with DNSSEC validation...
RRSIG verification FAILED!
RESULT: BOGUS - Possible DNS spoofing!

Implementation Hints:

DNSSEC adds these record types:

  • DNSKEY: Public key for the zone
  • RRSIG: Signature over a record set
  • DS: Hash of child zone’s DNSKEY (in parent zone)
  • NSEC/NSEC3: Proof of non-existence

Validation process:

def validate(domain, record_type):
    # 1. Get the records and their signature
    records = query(domain, record_type)
    rrsig = query(domain, "RRSIG")

    # 2. Get the zone's DNSKEY
    dnskey = query(domain_zone, "DNSKEY")

    # 3. Verify RRSIG using DNSKEY
    if not verify_signature(records, rrsig, dnskey):
        return "BOGUS"

    # 4. Verify DNSKEY using parent's DS record
    parent_ds = query(parent_zone, "DS")
    if hash(dnskey) != parent_ds.digest:
        return "BOGUS"

    # 5. Recursively verify parent up to root
    # (root keys are trusted by configuration)

    return "SECURE"

You’ll need a crypto library for RSA/ECDSA verification (e.g., cryptography in Python).

Learning milestones:

  1. You fetch DNSSEC records → You understand the new record types
  2. You verify one signature → You understand RRSIG
  3. You validate the full chain → You understand trust hierarchy
  4. You detect bogus responses → You can prevent spoofing

Project 12: DNS Zone Transfer Tool (AXFR)

  • File: LEARN_DNS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: C, Go
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Zone Transfers / TCP DNS
  • Software or Tool: AXFR client
  • Main Book: “DNS and BIND” by Paul Albitz & Cricket Liu

What you’ll build: A tool that requests full zone transfers (AXFR) from DNS servers, retrieving all records in a zone—useful for backup, migration, and security auditing.

Why it teaches DNS: Zone transfers show DNS replication. Secondary servers use AXFR to copy zones from primaries. Understanding this teaches you about DNS infrastructure, and why misconfigured AXFR is a security risk.

Core challenges you’ll face:

  • TCP DNS connections → maps to DNS over TCP with length prefix
  • AXFR query type → maps to special query that returns multiple responses
  • Parsing multi-message responses → maps to zone data can be large
  • Detecting transfer end → maps to second SOA indicates completion

Key Concepts:

  • AXFR: RFC 5936
  • TCP DNS: RFC 1035 Section 4.2.2
  • Zone Transfer Security: Why AXFR should be restricted
  • IXFR (Incremental): RFC 1995

Difficulty: Intermediate Time estimate: 1 week Prerequisites: Projects 1-2

Real world outcome:

# Many servers block AXFR, but some don't:
$ ./myaxfr zonetransfer.me @nsztm1.digi.ninja
Requesting zone transfer for zonetransfer.me from nsztm1.digi.ninja...

Zone Transfer Results:
zonetransfer.me.        7200    IN      SOA     nsztm1.digi.ninja. ...
zonetransfer.me.        7200    IN      NS      nsztm1.digi.ninja.
zonetransfer.me.        7200    IN      NS      nsztm2.digi.ninja.
zonetransfer.me.        7200    IN      A       5.196.105.14
zonetransfer.me.        7200    IN      MX      0 ASPMX.L.GOOGLE.COM.
www.zonetransfer.me.    7200    IN      A       5.196.105.14
email.zonetransfer.me.  7200    IN      A       74.125.206.26
...
zonetransfer.me.        7200    IN      SOA     nsztm1.digi.ninja. ...

Received 50 records in zone transfer.

# Export to zone file:
$ ./myaxfr zonetransfer.me @nsztm1.digi.ninja --output zone.txt
Saved zone to zone.txt

Implementation Hints:

AXFR is a special query type (252) that:

  1. Must be sent over TCP
  2. Returns multiple DNS messages
  3. Starts and ends with SOA record

Pseudo-code:

def axfr(domain, server):
    # Build AXFR query
    query = build_dns_query(domain, QTYPE_AXFR)

    # Connect via TCP
    sock = socket.create_connection((server, 53))

    # Send with length prefix
    sock.send(struct.pack(">H", len(query)) + query)

    records = []
    soa_count = 0

    while True:
        # Read length prefix
        length = struct.unpack(">H", sock.recv(2))[0]
        response = sock.recv(length)

        # Parse response
        message = parse_dns_response(response)

        for record in message.answers:
            records.append(record)
            if record.type == "SOA":
                soa_count += 1

        # Zone transfer ends with second SOA
        if soa_count >= 2:
            break

    return records

Learning milestones:

  1. TCP DNS works → You understand the length-prefixed format
  2. AXFR returns records → You understand zone transfers
  3. You export to zone file → You can backup DNS zones
  4. You understand the security risk → Open AXFR leaks all hostnames

Project 13: Dynamic DNS (DDNS) Client

  • File: LEARN_DNS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Bash
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Dynamic DNS / API Integration
  • Software or Tool: ddclient clone
  • Main Book: “DNS and BIND” by Paul Albitz & Cricket Liu

What you’ll build: A client that automatically updates your DNS record when your IP address changes—essential for home servers with dynamic IPs.

Why it teaches DNS: Dynamic DNS shows DNS as a living, changing system. You’ll understand DNS UPDATE (RFC 2136) or API-based updates, TTL implications, and how services like DynDNS and No-IP work.

Core challenges you’ll face:

  • Detecting IP changes -> maps to external IP discovery
  • DNS UPDATE protocol -> maps to RFC 2136 messages
  • API-based updates -> maps to Cloudflare, Route53, etc.
  • Authentication -> maps to TSIG or API keys
  • Running as a daemon -> maps to periodic checking

Key Concepts:

  • DNS UPDATE: RFC 2136
  • TSIG Authentication: RFC 2845
  • Provider APIs: Cloudflare, Route53, Google Domains
  • IP Detection: Services like ifconfig.me, ipify.org

Difficulty: Intermediate Time estimate: 1 week Prerequisites: Project 2

Real world outcome:

$ ./myddns --config config.yml
Dynamic DNS Client starting...
Current IP: 203.0.113.50
Checking every 300 seconds

# config.yml:
provider: cloudflare
zone: example.com
record: home.example.com
api_token: xxx

# First run:
[INIT] Current IP: 203.0.113.50
[UPDATE] home.example.com -> 203.0.113.50
[SUCCESS] DNS updated, TTL=300

# Later, when IP changes:
[CHECK] IP changed: 203.0.113.50 -> 198.51.100.25
[UPDATE] home.example.com -> 198.51.100.25
[SUCCESS] DNS updated, TTL=300

# Verification:
$ dig home.example.com
home.example.com.       300     IN      A       198.51.100.25

Implementation Hints:

Two approaches:

  1. API-based (common for cloud DNS):
    def update_cloudflare(zone_id, record_id, new_ip, api_token):
     response = requests.put(
         f"https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records/{record_id}",
         headers={"Authorization": f"Bearer {api_token}"},
         json={"type": "A", "content": new_ip}
     )
     return response.json()["success"]
    
  2. DNS UPDATE (RFC 2136): ``` Build UPDATE message: Header: opcode=UPDATE Zone section: the zone name Prerequisite section: (optional checks) Update section: add/delete records

Sign with TSIG if required Send via TCP to primary DNS server


*Daemon loop*:
  1. Get current external IP (ifconfig.me, ipify.org)
  2. Compare with last known IP
  3. If changed: a. Update DNS record via API or DNS UPDATE b. Save new IP
  4. Sleep for interval (5 minutes)
  5. Repeat ```

Learning milestones:

  1. You detect your external IP -> You understand NAT traversal
  2. API updates work -> You understand DNS management APIs
  3. Changes propagate -> You understand TTL and propagation
  4. Runs continuously -> You’ve built a useful daemon

Project 14: DNS Query Logger and Analyzer

  • File: LEARN_DNS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: DNS Monitoring / Analytics
  • Software or Tool: DNS logging/analytics
  • Main Book: “The Practice of Network Security Monitoring” by Richard Bejtlich

What you’ll build: A passive DNS monitor that logs all DNS queries on your network, analyzes patterns, detects anomalies, and provides insights into network behavior.

Why it teaches DNS: DNS traffic reveals what your network is doing. Logging and analyzing it teaches you about normal vs abnormal patterns, DNS tunneling detection, and security monitoring.

Core challenges you’ll face:

  • Passive packet capture -> maps to sniffing DNS traffic
  • Real-time parsing -> maps to performance at scale
  • Storage and indexing -> maps to time-series data
  • Anomaly detection -> maps to statistical analysis
  • Visualization -> maps to dashboards and reports

Key Concepts:

  • Passive DNS: Collecting DNS data from network traffic
  • DNS Tunneling Detection: Unusual query patterns
  • Threat Intelligence: Correlating with known-bad domains
  • Query Rate Analysis: Baseline and deviation

Difficulty: Intermediate Time estimate: 2 weeks Prerequisites: Project 1 (DNS Analyzer)

Real world outcome:

$ sudo ./mydns-monitor eth0 --dashboard
DNS Monitor starting on eth0...
Dashboard at http://localhost:8080

# Real-time log:
10:30:01 192.168.1.100 -> google.com A (8.8.8.8) 14ms
10:30:02 192.168.1.100 -> fonts.googleapis.com A (8.8.8.8) 12ms
10:30:05 192.168.1.105 -> suspicious-domain.xyz A (8.8.8.8) 23ms [!]
10:30:06 192.168.1.100 -> api.github.com A (8.8.8.8) 11ms

# Dashboard shows:
- Total queries: 12,345
- Unique domains: 456
- Top clients: 192.168.1.100 (5,432), 192.168.1.105 (3,210)
- Top domains: google.com (234), facebook.com (189)
- Anomalies detected: 3
  - High query rate from 192.168.1.105 (possible tunnel)
  - Unknown TLD .xyz (possible malware)
  - Long subdomain (possible data exfiltration)

Implementation Hints:

Architecture:

[Network] -> [Packet Capture] -> [DNS Parser] -> [Database]
                                                      |
                                              [Analyzer] -> [Dashboard]

Pseudo-code:

1. Capture DNS packets (UDP port 53)
2. For each packet:
   a. Parse DNS message
   b. Extract: timestamp, client IP, query domain, type, response
   c. Store in database (SQLite for simple, TimescaleDB for scale)
3. Background analyzer:
   a. Calculate baselines (queries per minute, domain distribution)
   b. Detect anomalies:
      - Unusual query volume
      - Long domain names (tunneling)
      - High entropy subdomain (DGA/exfiltration)
      - Known-bad domains (threat intel)
4. Web dashboard for visualization

Anomaly indicators:

  • Subdomain length > 30 chars (possible tunnel)
  • Query rate > 10x baseline (possible attack)
  • Domain entropy > 3.5 (possible DGA)

Learning milestones:

  1. You capture and log queries -> You understand passive DNS
  2. Patterns emerge -> You understand normal DNS behavior
  3. Anomalies are detected -> You understand DNS security
  4. Dashboard visualizes data -> You can present insights

Project 15: DNS Load Balancer

  • File: LEARN_DNS.md
  • Main Programming Language: Go
  • Alternative Programming Languages: C, Rust
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 3: Advanced
  • Knowledge Area: DNS-Based Load Balancing
  • Software or Tool: Simple GSLB
  • Main Book: “DNS and BIND” by Paul Albitz & Cricket Liu

What you’ll build: A DNS server that returns different IP addresses based on server health, geographic location, or round-robin—implementing DNS-based load balancing.

Why it teaches DNS: DNS-based load balancing is how CDNs and large services distribute traffic. Understanding it teaches you about response crafting, health checks, and the limitations of DNS TTL in load balancing.

Core challenges you’ll face:

  • Health checking backends -> maps to monitoring server availability
  • Round-robin responses -> maps to simple load distribution
  • Weighted responses -> maps to capacity-aware routing
  • Geographic routing -> maps to GeoIP lookup
  • TTL considerations -> maps to DNS caching vs freshness

Key Concepts:

  • GSLB (Global Server Load Balancing): Multi-datacenter load balancing
  • Health Checks: Verifying backend availability
  • DNS Round-Robin: RFC 1794
  • GeoIP: MaxMind, IP2Location databases

Difficulty: Advanced Time estimate: 2-3 weeks Prerequisites: Project 4 (Authoritative DNS)

Real world outcome:

$ ./mydns-lb --config lb-config.yml
DNS Load Balancer starting...
Zone: app.example.com
Backends:
  dc-east: 10.0.1.10, 10.0.1.11 (weight: 50)
  dc-west: 10.0.2.10, 10.0.2.11 (weight: 50)

Health checks every 10s...
[HEALTHY] 10.0.1.10 (dc-east) - 5ms
[HEALTHY] 10.0.1.11 (dc-east) - 6ms
[HEALTHY] 10.0.2.10 (dc-west) - 4ms
[UNHEALTHY] 10.0.2.11 (dc-west) - timeout

# Queries return healthy backends:
$ dig @localhost app.example.com
app.example.com.        60      IN      A       10.0.1.10
app.example.com.        60      IN      A       10.0.2.10

# Next query (round-robin):
$ dig @localhost app.example.com
app.example.com.        60      IN      A       10.0.1.11
app.example.com.        60      IN      A       10.0.2.10

# Geographic query from Europe:
$ dig @localhost app.example.com  # (from EU IP)
app.example.com.        60      IN      A       10.0.3.10  # EU datacenter

Implementation Hints:

Config format:

zone: app.example.com
ttl: 60  # Low TTL for faster failover
health_check:
  interval: 10s
  timeout: 5s
  path: /health

backends:
  - name: dc-east
    ips: [10.0.1.10, 10.0.1.11]
    weight: 50
    geo: [US, CA]
  - name: dc-west
    ips: [10.0.2.10, 10.0.2.11]
    weight: 50
    geo: [EU, UK]

Pseudo-code:

1. Load backend configuration
2. Start health check goroutine/thread:
   - Every interval, HTTP GET /health on each backend
   - Mark backends healthy/unhealthy
3. Listen for DNS queries
4. For each query:
   a. Get client IP (from EDNS Client Subnet if available)
   b. Lookup client geo (GeoIP database)
   c. Filter backends by:
      - Health status (only healthy)
      - Geographic preference (match client region)
   d. Select N backends by:
      - Round-robin or
      - Weighted random
   e. Build DNS response with selected IPs
   f. Set low TTL for quick failover

Learning milestones:

  1. Health checks work -> You understand backend monitoring
  2. Round-robin rotates IPs -> You understand basic load balancing
  3. Unhealthy servers are excluded -> You understand failover
  4. Geo-routing works -> You understand geographic load balancing

Project 16: Authoritative DNS Server with DNSSEC Signing

  • File: LEARN_DNS.md
  • Main Programming Language: C
  • Alternative Programming Languages: Go, Rust
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 5: Master
  • Knowledge Area: DNSSEC / Cryptographic Signing
  • Software or Tool: DNSSEC-enabled authoritative server
  • Main Book: “Serious Cryptography” by Jean-Philippe Aumasson

What you’ll build: An authoritative DNS server that signs its zones with DNSSEC, generating RRSIG records, maintaining DNSKEY pairs, and supporting key rollover.

Why it teaches DNS: This is the server side of DNSSEC. You’ll understand key management, signature generation, NSEC/NSEC3 for negative responses, and the operational complexity that makes DNSSEC adoption challenging.

Core challenges you’ll face:

  • Key pair generation and management -> maps to KSK and ZSK
  • Signing RRsets -> maps to RRSIG generation
  • NSEC/NSEC3 chain creation -> maps to authenticated denial
  • Key rollover procedures -> maps to operational security
  • DS record publication -> maps to parent zone coordination

Key Concepts:

  • Zone Signing: RFC 4035 Section 2
  • NSEC vs NSEC3: RFC 5155
  • Key Rollover: RFC 7583
  • DS Record: RFC 4034 Section 5

Resources for key challenges:

Difficulty: Master Time estimate: 4-6 weeks Prerequisites: Projects 4 and 11, strong cryptography understanding

Real world outcome:

$ ./mydns-signed --zone myzone.example.com --keydir keys/
Generating DNSSEC keys...
  KSK: myzone.example.com. algorithm=ECDSAP256SHA256 id=12345
  ZSK: myzone.example.com. algorithm=ECDSAP256SHA256 id=67890

Signing zone...
  Signed 25 RRsets
  Generated 25 RRSIG records
  Generated NSEC chain (15 records)

DS record for parent zone:
myzone.example.com. IN DS 12345 13 2 ABCD1234...

Server listening on port 53...

# Queries include RRSIG:
$ dig @localhost www.myzone.example.com +dnssec
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 2
;; ANSWER SECTION:
www.myzone.example.com.  86400  IN  A     192.0.2.1
www.myzone.example.com.  86400  IN  RRSIG A 13 3 86400 ...

# Validation works:
$ dig @localhost www.myzone.example.com +dnssec +cd  # validation disabled
$ dig @localhost www.myzone.example.com +dnssec      # validation enabled
;; flags: ... ad  # "ad" = authenticated data

Implementation Hints:

DNSSEC signing process:

1. Generate keys:
   - KSK (Key Signing Key): signs DNSKEY RRset
   - ZSK (Zone Signing Key): signs everything else

2. For each RRset in zone:
   - Sort records canonically
   - Create RRSIG with:
     - Algorithm, labels, original TTL
     - Signature expiration and inception times
     - Key tag (identifies which key signed)
     - Signer name
     - Signature (cryptographic)

3. Generate NSEC chain:
   - Sort all names in zone
   - For each name, create NSEC pointing to next name
   - NSEC lists which types exist at this name
   - Sign all NSEC records too

4. Publish DS record to parent:
   - Hash of KSK
   - Parent zone adds it (manual or API)

Key rollover (simplified):

Pre-publish method:
1. Generate new ZSK
2. Add new DNSKEY (both old and new active)
3. Wait for TTL expiration
4. Re-sign zone with new ZSK
5. Remove old DNSKEY

Learning milestones:

  1. Keys are generated correctly -> You understand DNSSEC key types
  2. RRSIGs validate -> You understand signature generation
  3. NSEC proves non-existence -> You understand negative responses
  4. Key rollover works -> You understand DNSSEC operations

Project 17: Complete DNS Infrastructure Stack (Capstone)

  • File: LEARN_DNS.md
  • Main Programming Language: Multiple (C, Python, Go)
  • Alternative Programming Languages: Rust
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 5: Master
  • Knowledge Area: Full DNS Stack
  • Software or Tool: Complete DNS platform
  • Main Book: All books referenced above

What you’ll build: A complete DNS infrastructure: authoritative servers, recursive resolvers, caching, DNSSEC signing, DoH/DoT support, monitoring, and a web management interface—your own mini Cloudflare DNS.

Why it teaches DNS: This capstone integrates everything. You’ll run production-grade DNS infrastructure, handle real traffic, and understand the operational complexity of DNS at scale.

Core challenges you’ll face:

  • Integrating all previous projects -> maps to systems integration
  • High availability -> maps to redundancy and failover
  • Performance at scale -> maps to optimization
  • Operational tooling -> maps to management and monitoring
  • Security hardening -> maps to attack mitigation

Key Concepts:

  • All previous concepts combined
  • Anycast: Same IP from multiple locations
  • Rate Limiting: Preventing DNS amplification
  • EDNS Client Subnet: Passing client location info

Difficulty: Master Time estimate: 2-3 months Prerequisites: All previous projects

Real world outcome:

$ ./mydns-platform start
Starting DNS Platform...

[OK] Primary authoritative (ns1.example.com:53)
[OK] Secondary authoritative (ns2.example.com:53)
[OK] Recursive resolver (resolver.example.com:53)
[OK] DoH endpoint (https://dns.example.com/dns-query)
[OK] DoT endpoint (dns.example.com:853)
[OK] DNSSEC signing active
[OK] Monitoring dashboard (http://admin.example.com:8080)
[OK] API server (http://api.example.com:8081)

# Web dashboard shows:
- Queries/second: 1,234
- Cache hit rate: 89%
- Active zones: 15
- DNSSEC status: All zones signed
- Health: All servers healthy
- Alerts: None

# API for zone management:
$ curl -X POST https://api.example.com/zones \
    -H "Authorization: Bearer xxx" \
    -d '{"zone": "newzone.example.com", "records": [...]}'
{"status": "created", "zone_id": "abc123"}

Implementation Hints:

Architecture:

                         +------------------+
                         |   Load Balancer  |
                         +--------+---------+
                                  |
        +-------------------------+-------------------------+
        |                         |                         |
+-------v-------+        +--------v--------+       +--------v--------+
|  Authoritative|        |    Recursive    |       |   DoH/DoT       |
|  DNS Server   |        |    Resolver     |       |   Proxy         |
+-------+-------+        +--------+--------+       +--------+--------+
        |                         |                         |
        +-------------------------+-------------------------+
                                  |
                         +--------v--------+
                         |  Cache Layer    |
                         +-----------------+
                                  |
                         +--------v--------+
                         |   Database      |
                         |  (zones, keys)  |
                         +-----------------+
                                  |
                         +--------v--------+
                         |   Monitoring    |
                         |   Dashboard     |
                         +-----------------+

Components to integrate:

  • Authoritative server (Project 4) with DNSSEC (Project 16)
  • Caching resolver (Project 5)
  • DoH proxy (Project 10)
  • Sinkhole/filtering (Project 6)
  • Query logging (Project 14)
  • Health monitoring
  • Web UI for management
  • API for automation

Learning milestones:

  1. All components run together -> You understand system integration
  2. Failover works -> You understand high availability
  3. Performance is acceptable -> You understand optimization
  4. You can manage via UI/API -> You understand operations
  5. External clients use your DNS -> You’re running real infrastructure

Project 18: DNS Wire-Format Inspector

  • File: LEARN_DNS.md
  • Main Programming Language: C
  • Alternative Programming Languages: Rust, Go, Python
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Network Protocols / Binary Parsing
  • Software or Tool: DNS message encoder/decoder
  • Main Book: Computer Networks by Tanenbaum & Wetherall

What you’ll build: A CLI that reads raw DNS packets (hex, pcap, or stdin) and prints a structured decode of header/sections, including name compression pointers.

Why it teaches DNS: If you cannot decode a DNS packet yourself, everything else becomes guesswork. This forces you to learn the message format, label encoding, and the exact meaning of flags and RCODEs.

Core challenges you’ll face:

  • Parsing variable-length sections safely (maps to wire format)
  • Implementing name decoding with compression and loop detection (maps to compression mechanics)
  • Displaying RR data correctly for common types (maps to RR semantics)

Key Concepts

  • DNS message format: RFC 1035 (message sections and fields)
  • Name compression: RFC 1035 (compression rules)
  • RR type registry mindset: IANA DNS Parameters (how types/classes evolve)

Difficulty: Intermediate Time estimate: Weekend Prerequisites: Comfort with byte arrays, endian issues, and basic UDP socket concepts

Real world outcome

  • You can capture a DNS query/response from your machine and your tool prints the same logical structure you see in professional tooling (flags, question, answers, authority, additional).
  • You can feed malformed packets and observe graceful error reporting (no crashes).

Implementation Hints

  • Start with a strict “cursor + bounds” model: every read is bounds-checked.
  • Treat every length field and pointer as untrusted. Add recursion depth limits for compressed-name decoding.

Learning milestones

  1. Correct header + question parsing → you understand the skeleton of DNS wire format
  2. Correct name compression decoding → you understand why DNS parsing is trickier than “binary structs”
  3. Correct multi-RR parsing → you can now build real DNS clients/servers confidently

Project 19: Minimal “dig” Clone (UDP Stub Resolver)

  • File: LEARN_DNS.md
  • Main Programming Language: C
  • Alternative Programming Languages: Rust, Go, Python
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Networking / Client Protocols
  • Software or Tool: DNS client
  • Main Book: DNS and BIND by Cricket Liu & Paul Albitz

What you’ll build: A CLI that sends a DNS query to a chosen resolver and prints the response in a concise, deterministic format (A/AAAA/CNAME/MX/TXT at minimum).

Why it teaches DNS: You learn query construction, transaction IDs, retransmits, and how “simple” stub resolvers actually behave.

Core challenges you’ll face:

  • Encoding QNAME/QTYPE/QCLASS correctly (maps to message construction)
  • Handling timeouts and retries (maps to real network conditions)
  • Parsing the answer section robustly (maps to RR decoding)

Key Concepts

  • Query/response semantics: RFC 1035
  • UDP limits and truncation awareness: RFC 1035 plus TCP requirements: RFC 7766

Difficulty: Intermediate Time estimate: Weekend Prerequisites: DNS Wire-Format Inspector (Project 18 recommended), UDP sockets

Real world outcome

  • When you query common domains, your printed answers match a trusted tool’s answers (records and TTL ranges).
  • You can query a resolver you control and see authoritative vs recursive differences.

Implementation Hints

  • Start with recursion disabled and observe how replies differ when RD is off.
  • Add a reproducible output mode that sorts RRsets deterministically for testing.

Learning milestones

  1. A/AAAA queries work end-to-end → you understand the “hello world” of DNS
  2. CNAME chains are printed clearly → you understand aliasing and multi-step resolution
  3. Robust retry/timeout behavior → you understand DNS under loss and latency

Project 20: Zone File Parser & Linter (“named-checkzone” Lite)

  • File: LEARN_DNS.md
  • Main Programming Language: Rust
  • Alternative Programming Languages: Go, Python, C++
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Parsing / Configuration Validation
  • Software or Tool: Zone file linter
  • Main Book: DNS and BIND by Cricket Liu & Paul Albitz

What you’ll build: A zone file parser that validates SOA/NS structure, TTL rules, and common mistakes (missing trailing dot, illegal CNAME coexistence, etc.).

Why it teaches DNS: Zones are how DNS is operated. This project makes you learn what operators publish and what breaks delegation.

Core challenges you’ll face:

  • Parsing a context-sensitive text format (origin, relative names, multi-line records) (maps to zone representation)
  • Validating zone apex invariants (SOA required, NS required) (maps to delegation correctness)
  • Producing actionable error messages (maps to operational thinking)

Key Concepts

  • Zones vs domains: DNS and BIND (zones, delegation, SOA/NS)
  • Record constraints baseline: RFC 1034/1035

Difficulty: Intermediate Time estimate: 1–2 weeks Prerequisites: Basic parsing experience; familiarity with RR types

Real world outcome

  • You can lint a real zone file and catch issues that would break production DNS.
  • You can output a canonical, stable ordering of records for clean Git diffs.

Implementation Hints

  • Separate parsing from validation: parse into a structured representation, then run invariants.
  • Make $ORIGIN, $TTL, and relative names first-class.

Learning milestones

  1. Parse common zones → you understand how zones are authored
  2. Catch real misconfigurations → you understand operational failure modes
  3. Canonical output stability → you understand why DNS tooling favors determinism

Project 21: Minimal Authoritative DNS Server (UDP)

  • File: LEARN_DNS.md
  • Main Programming Language: C
  • Alternative Programming Languages: Rust, Go, C++
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Network Servers / Protocol Semantics
  • Software or Tool: Authoritative DNS server
  • Main Book: DNS and BIND by Cricket Liu & Paul Albitz

What you’ll build: An authoritative DNS server that serves one zone from memory (A/AAAA/CNAME/NS/SOA/TXT), returning authoritative answers, NXDOMAIN, and referrals correctly.

Why it teaches DNS: Authoritative DNS is where correctness matters. You must model zones, authoritative flags, and the difference between “I don’t know” and “it doesn’t exist.”

Core challenges you’ll face:

  • Correct response flags (AA, RD, RA, RCODE) (maps to protocol semantics)
  • NXDOMAIN vs NODATA behavior (maps to negative answers)
  • Referrals and glue logic (maps to delegation behavior)

Key Concepts

  • Authoritative answers and delegation: RFC 1034/1035
  • Negative caching implications (SOA in authority section): RFC 2308

Difficulty: Advanced Time estimate: 2–3 weeks Prerequisites: Projects 18–20, UDP server fundamentals

Real world outcome

  • Your server answers authoritatively for your zone and returns correct NXDOMAIN vs NODATA semantics.
  • It can return a referral (NS) for a delegated child zone.

Implementation Hints

  • Start with an in-memory zone produced by your Zone File Parser.
  • Implement CNAME chaining with loop limits.

Learning milestones

  1. Basic authoritative answers → you understand AA, zone apex, and RRsets
  2. Correct negative responses → you understand NXDOMAIN/NODATA and why operators care
  3. Correct delegation/referral behavior → you understand how the DNS tree is stitched together

Project 22: Iterative Recursive Resolver (Root-to-Authoritative Walker)

  • File: LEARN_DNS.md
  • Main Programming Language: Rust
  • Alternative Programming Languages: Go, C, Python
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Distributed Systems / Resolution Algorithms
  • Software or Tool: Recursive resolver
  • Main Book: Computer Networks by Tanenbaum & Wetherall

What you’ll build: A resolver that performs iterative resolution: start from a root hint set, follow referrals, handle glue, chase CNAMEs, and return a final answer.

Why it teaches DNS: This is the heart of DNS. Building it forces you to understand delegations, bailiwick, and the real meaning of “recursive.”

Core challenges you’ll face:

  • Following referrals safely (NS records + glue vs additional-data traps) → maps to delegation traversal
  • Implementing CNAME chasing with loop detection → maps to graph traversal
  • Handling timeouts and partial failures across multiple upstreams → maps to distributed failure handling

Key Concepts

  • Iterative resolution mechanics: RFC 1034
  • Forgery-resilience mindset (transaction IDs + source ports, etc.): RFC 5452

Difficulty: Advanced Time estimate: 1 month+ Prerequisites: Strong comfort with networking, Projects 18–21

Real world outcome

  • You can resolve a domain without using any OS resolver library: your resolver walks root → TLD → authoritative and returns the final RRset.
  • You can log each hop and visually see delegation in action.

Implementation Hints

  • Keep a “query plan” structure: current name/type plus a list of candidate name servers to try.
  • Add bailiwick checks early: do not blindly cache or trust “additional” records outside the delegated scope.

Learning milestones

  1. Root-to-TLD referrals work → you understand delegation in practice
  2. CNAME chains work across zones → you understand multi-zone name resolution
  3. Robustness under partial failure → you understand why resolvers are engineering-heavy systems

Project 23: Caching Resolver with Negative Caching

  • File: LEARN_DNS.md
  • Main Programming Language: Rust
  • Alternative Programming Languages: Go, C++, Java
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Caching / Correctness Under Time
  • Software or Tool: Recursive resolver cache
  • Main Book: Designing Data-Intensive Applications by Martin Kleppmann

What you’ll build: Add a resolver cache: RRset caching with TTL countdown, negative caching for NXDOMAIN/NODATA, and sane eviction policies.

Why it teaches DNS: DNS caching is where correctness and security collide. Incorrect caching breaks user resolution; insecure caching enables poisoning.

Core challenges you’ll face:

  • TTL handling and “time to die” semantics per RRset → maps to time-based caching
  • Negative caching behavior and SOA-derived TTL rules → maps to negative caching correctness
  • Cache keying and bailiwick boundaries → maps to trust boundaries

Key Concepts

  • Negative caching: RFC 2308
  • TCP fallback and truncation behavior: RFC 7766

Difficulty: Advanced Time estimate: 2–4 weeks Prerequisites: Iterative resolver (Project 22), solid data-structure skills

Real world outcome

  • Repeated queries become fast and produce fewer upstream packets (observable in traffic capture).
  • NXDOMAIN and NODATA results cache correctly and expire when expected.

Implementation Hints

  • Cache RRsets (name + type + class) rather than single records; treat an RRset as atomic.
  • Record provenance: which authority provided the data and whether it was in-bailiwick.

Learning milestones

  1. Positive caching works → you understand TTL and RRset identity
  2. Negative caching works → you understand NXDOMAIN/NODATA semantics in practice
  3. Cache correctness under churn → you understand why resolver bugs are so impactful

Project 24: DNS over TCP (Client + Server) and Truncation Handling

  • File: LEARN_DNS.md
  • Main Programming Language: C
  • Alternative Programming Languages: Rust, Go, Python
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Transport Protocol Engineering
  • Software or Tool: DNS transport implementation
  • Main Book: TCP/IP Illustrated, Volume 1 by Stevens & Wright

What you’ll build: Implement DNS message exchange over TCP (length-prefixed framing), add TCP fallback when UDP responses are truncated, and optionally serve queries over TCP in your authoritative server.

Why it teaches DNS: TCP is not optional for real DNS. Large answers, DNSSEC, and some failure modes require TCP. Implementing it forces you to treat DNS as a protocol family, not “UDP packets.”

Core challenges you’ll face:

  • Length-prefixed framing and partial reads/writes → maps to stream parsing
  • Connection reuse and concurrency decisions → maps to server architecture
  • Correct fallback logic using TC bit and retry semantics → maps to resolver behavior

Key Concepts

  • DNS over TCP requirements: RFC 7766
  • Core DNS message rules that still apply: RFC 1035

Difficulty: Advanced Time estimate: 2–3 weeks Prerequisites: UDP client/server, familiarity with TCP streams

Real world outcome

  • When you query for “large” answers, your client automatically retries over TCP and succeeds.
  • Your authoritative server can respond over TCP to standard clients.

Implementation Hints

  • Treat TCP reads as “may return fewer bytes than requested.” Build a small framing reader.
  • Add a max in-flight queries limit per connection to avoid self-DoS.

Learning milestones

  1. TCP query works → you understand framing and stream parsing
  2. UDP truncation triggers TCP fallback → you understand real resolver behavior
  3. Stable behavior under load → you understand why TCP in DNS is operationally tricky

Project 25: EDNS(0) Capability and UDP Payload Negotiation

  • File: LEARN_DNS.md
  • Main Programming Language: Rust
  • Alternative Programming Languages: C, Go, Python
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Protocol Extensibility
  • Software or Tool: EDNS(0) support (OPT RR)
  • Main Book: DNS and BIND by Cricket Liu & Paul Albitz

What you’ll build: Add EDNS(0) support to your client/resolver/server: send OPT records, advertise UDP buffer size, and handle extended RCODEs and options scaffolding.

Why it teaches DNS: Modern DNS relies on extensibility. EDNS(0) is how the protocol escaped the original 512-byte UDP ceiling and is a prerequisite for many features.

Core challenges you’ll face:

  • Modeling the OPT pseudo-RR and additional-section semantics → maps to protocol evolution
  • Handling larger UDP responses safely → maps to packet size constraints
  • Graceful fallback when EDNS is not supported upstream → maps to interoperability

Key Concepts

  • EDNS(0): RFC 6891

Difficulty: Advanced Time estimate: 1–2 weeks Prerequisites: Solid wire-format understanding, Projects 18–19

Real world outcome

  • Your resolver negotiates larger answers without switching to TCP unnecessarily.
  • You can detect and log EDNS negotiation failures cleanly.

Implementation Hints

  • Keep EDNS options parsing generic (TLV-like), so you can add Cookies later.
  • Prefer conservative UDP payload sizes; test across diverse networks.

Learning milestones

  1. OPT RR sent and parsed → you understand EDNS scaffolding
  2. Large-answer success improves → you understand UDP DNS constraints
  3. Interop fallback works → you understand real-world heterogeneity

Project 26: QNAME Minimization (Privacy Hardening in Your Resolver)

  • File: LEARN_DNS.md
  • Main Programming Language: Rust
  • Alternative Programming Languages: Go, C++, C
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 4: Expert
  • Knowledge Area: Privacy / Resolver Behavior
  • Software or Tool: Recursive resolver enhancement
  • Main Book: DNS and BIND by Cricket Liu & Paul Albitz

What you’ll build: Modify your iterative resolver to implement QNAME minimization: send only the minimal name needed at each step, instead of the full original name.

Why it teaches DNS: It forces you to understand exactly what each authority needs to know, clarifying delegation boundaries and referral semantics.

Core challenges you’ll face:

  • Decomposing a name into delegation-relevant query steps → maps to namespace traversal
  • Handling exceptions (CNAMEs, wildcards, unusual delegations) → maps to edge-case semantics
  • Maintaining cache correctness and reuse → maps to privacy/performance tradeoffs

Key Concepts

  • QNAME minimization: RFC 9156 (obsoletes RFC 7816)

Difficulty: Expert Time estimate: 2–4 weeks Prerequisites: Working iterative + caching resolver (Projects 22–23)

Real world outcome

  • Packet capture shows upstream queries leak less information than a non-minimizing resolver.
  • Resolution still succeeds for common domains and known tricky cases.

Implementation Hints

  • Introduce a “resolution context” that tracks discovered zone cuts and authoritative targets.
  • Build a regression suite of tricky domains and keep it stable as you evolve.

Learning milestones

  1. Basic minimization works → you understand minimum information per hop
  2. Edge cases handled → you understand where DNS semantics get subtle
  3. Stable cache behavior → you understand privacy/performance composition

Project 27: DNS Cookies Support (Anti-Forgery Hardening)

  • File: LEARN_DNS.md
  • Main Programming Language: C
  • Alternative Programming Languages: Rust, Go, C++
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 4: Expert
  • Knowledge Area: Security / Protocol Options
  • Software or Tool: DNS Cookies (EDNS option)
  • Main Book: Serious Cryptography by Jean-Philippe Aumasson

What you’ll build: Add DNS Cookies as EDNS options to your resolver and/or authoritative server to reduce off-path spoofing and improve transaction robustness.

Why it teaches DNS: It shows how modern DNS adds incremental security via EDNS options—without jumping straight to DNSSEC—and forces you to handle option negotiation and state.

Core challenges you’ll face:

  • EDNS option parsing and state tracking (maps to EDNS extensibility)
  • Cookie generation/validation policy (maps to security tradeoffs)
  • Interop constraints such as anycast-like deployments (maps to real-world DNS operations)

Key Concepts

  • DNS Cookies: RFC 7873
  • Anycast-friendly server cookies: RFC 9018
  • EDNS options carrier: RFC 6891

Difficulty: Expert Time estimate: 2–4 weeks Prerequisites: EDNS(0) support (Project 25), comfort with hashing/MAC concepts

Real world outcome

  • Your resolver/server can negotiate cookies and you can observe when cookie-less queries are treated differently (per your policy).
  • You can demonstrate reduced acceptance of spoof-like traffic in controlled lab tests.

Implementation Hints

  • Keep cryptographic primitives isolated behind a tiny interface; do not spread them across protocol code.
  • Make cookie negotiation visible via logs and counters.

Learning milestones

  1. Cookies negotiated and echoed correctly → you understand EDNS option lifecycles
  2. Validation policy enforced → you understand practical DNS hardening
  3. Interop tests pass across clients → you understand deployment constraints

Project 28: DNS-over-TLS (DoT) Client + Forwarder

  • File: LEARN_DNS.md
  • Main Programming Language: Go
  • Alternative Programming Languages: Rust, C++, Python
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Security / Transport
  • Software or Tool: DoT forwarder
  • Main Book: Computer Networks by Tanenbaum & Wetherall

What you’ll build: A DoT client and a local forwarder that accepts classic DNS locally and forwards upstream over TLS.

Why it teaches DNS: You will see DNS as an application protocol carried over secure transports, and you will confront stream framing plus TLS validation.

Core challenges you’ll face:

  • DNS-over-TCP framing inside TLS (maps to stream handling)
  • TLS certificate validation and name checking (maps to PKI reality)
  • Explicit fallback and policy design (maps to operational tradeoffs)

Key Concepts

  • DoT: RFC 7858
  • DNS over TCP requirements: RFC 7766

Difficulty: Advanced Time estimate: 2–3 weeks Prerequisites: DNS-over-TCP (Project 24), basic TLS client knowledge

Real world outcome

  • Your local machine can send DNS to your forwarder and your forwarder encrypts upstream DNS traffic using TLS.
  • Packet capture shows encrypted traffic instead of plaintext DNS on UDP/53.

Implementation Hints

  • Make policy explicit: timeouts, retries, fallback to UDP or not, and logging.
  • Observability is mandatory; debugging DoT without logs is painful.

Learning milestones

  1. Single DoT query works → you understand DNS framing over encrypted streams
  2. Local forwarder works reliably → you understand integration into real systems
  3. Robust policy and fallback → you understand production constraints

Project 29: DNS-over-HTTPS (DoH) Client + Forwarder

  • File: LEARN_DNS.md
  • Main Programming Language: Go
  • Alternative Programming Languages: Rust, Python, Java
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Security / HTTP Semantics
  • Software or Tool: DoH forwarder
  • Main Book: Design and Build Great Web APIs by Mike Amundsen

What you’ll build: A DoH client (GET and POST forms) and a local forwarder that translates classic DNS packets into DoH requests.

Why it teaches DNS: You learn how DNS messages map to HTTP exchanges, how failure modes differ, and how encrypted DNS affects network policy and observability.

Core challenges you’ll face:

  • DNS wire format as an HTTP payload (maps to protocol encapsulation)
  • HTTP caching vs DNS TTL semantics (maps to cache mismatch pitfalls)
  • Distinguishing HTTP errors from DNS errors (maps to error taxonomy)

Key Concepts

  • DoH: RFC 8484
  • DNS wire format: RFC 1035

Difficulty: Advanced Time estimate: 2–3 weeks Prerequisites: Projects 18–19, solid HTTP client knowledge

Real world outcome

  • Applications that only speak classic DNS can reach a DoH upstream via your local forwarder.
  • You can compare responses from your forwarder against another known-good DoH endpoint.

Implementation Hints

  • Keep the forwarder packet-faithful: do not reinterpret DNS; transport it.
  • Export metrics: latency, HTTP status codes, DNS RCODEs, fallback counts.

Learning milestones

  1. DoH query works → you understand DNS-in-HTTP mapping
  2. Forwarder works end-to-end → you understand DoH plumbing
  3. Clear error taxonomy → you understand operational debugging of DoH

Project 30: DNSSEC Validator (Recursive Validation Mode)

  • File: LEARN_DNS.md
  • Main Programming Language: Rust
  • Alternative Programming Languages: Go, C++, Java
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 4: Expert
  • Knowledge Area: Cryptography / Protocol Verification
  • Software or Tool: DNSSEC validation engine
  • Main Book: Serious Cryptography by Jean-Philippe Aumasson

What you’ll build: Extend your resolver to validate DNSSEC: build and verify chains of trust from a trust anchor, validate DNSKEY/DS/RRSIG, and handle authenticated denial of existence (NSEC/NSEC3 as a later extension).

Why it teaches DNS: DNSSEC forces you to understand zone cuts, delegation, and authenticity precisely. It turns “best effort resolution” into “provably correct or fail.”

Core challenges you’ll face:

  • Building the chain of trust across delegations (maps to DNS hierarchy truth)
  • Signature verification and canonicalization issues (maps to crypto meets protocol encoding)
  • Correctly handling “secure/insecure/bogus/indeterminate” states (maps to resolver security UX)

Resources for key challenges:

  • RFC 4034 — DNSKEY/DS/RRSIG/NSEC records and semantics
  • RFC 4035 — DNSSEC protocol modifications

Key Concepts

  • DNSSEC overview and requirements: RFC 4033
  • DNSSEC record types and formats: RFC 4034
  • DNSSEC protocol behavior: RFC 4035

Difficulty: Expert Time estimate: 1–2 months Prerequisites: Iterative + caching resolver, comfort with cryptographic primitives

Real world outcome

  • Your resolver can report whether an answer is validated, unsigned, or bogus, and it fails closed for zones that should validate.
  • You can demonstrate the difference between unsigned and signed zones in a test lab.

Implementation Hints

  • Treat DNSSEC as a verifier module with explicit inputs/outputs; keep it out of transport code.
  • Start with a minimal algorithm set and expand later.

Learning milestones

  1. Validate a simple signed test zone → you understand trust anchors and DS/DNSKEY linkage
  2. Validate real-world signed domains → you understand operational DNSSEC realities
  3. Handle denial-of-existence correctly → you understand why DNSSEC is hard in production

Project 31: AXFR Zone Transfer Client + Secondary Zone Store

  • File: LEARN_DNS.md
  • Main Programming Language: Go
  • Alternative Programming Languages: Rust, Python, C++
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Replication / DNS Operations
  • Software or Tool: AXFR client and zone store
  • Main Book: DNS and BIND by Cricket Liu & Paul Albitz

What you’ll build: An AXFR client that performs full zone transfers from a master, stores the zone locally, and can serve it via your authoritative server as a “secondary.”

Why it teaches DNS: This is how real DNS deployments replicate zones. It forces you to understand SOA serials, transfer framing, and operational coherence.

Core challenges you’ll face:

  • TCP-based multi-message transfer parsing (maps to stream decoding at scale)
  • SOA serial comparison logic (maps to change detection)
  • Storing RRsets and serving them efficiently (maps to data modeling)

Key Concepts

  • AXFR protocol: RFC 5936
  • DNS over TCP requirements: RFC 7766

Difficulty: Advanced Time estimate: 2–4 weeks Prerequisites: DNS-over-TCP project, zone representation from Project 20

Real world outcome

  • You can transfer a zone from a master in your lab and answer authoritatively from your secondary store.
  • You can demonstrate that changes on the master propagate when the SOA serial increases.

Implementation Hints

  • Treat transfers as a sequence of DNS messages containing RRs; do not invent a new format.
  • Enforce access controls in your lab; zone transfers are sensitive operationally.

Learning milestones

  1. Transfer and parse → you understand zone replication mechanics
  2. Store + serve as secondary → you understand authoritative serving backed by replication
  3. Handle large zones → you understand streaming and memory constraints

Project 32: Dynamic DNS Update Client (RFC 2136) + Audit Log

  • File: LEARN_DNS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Rust, C++
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: DNS Operations / Change Management
  • Software or Tool: Dynamic update (DDNS) client
  • Main Book: DNS and BIND by Cricket Liu & Paul Albitz

What you’ll build: A client that performs atomic DNS updates (add/remove RRsets) against a server that supports dynamic updates, and writes a tamper-evident audit log of what changed.

Why it teaches DNS: It forces you to understand that DNS can be a mutable database (especially internally), and that “update” is its own protocol with prerequisites and atomicity.

Core challenges you’ll face:

  • Constructing UPDATE messages with prerequisites (maps to non-query opcodes)
  • Interpreting result codes and partial failures (maps to operational correctness)
  • Designing an audit trail operators can trust (maps to real-world operations)

Key Concepts

  • Dynamic update protocol: RFC 2136
  • Update authentication concept (TSIG extension): RFC 8945 (recommended next)

Difficulty: Advanced Time estimate: 2–3 weeks Prerequisites: Wire-format encoding competence, strong testing discipline

Real world outcome

  • You can update a record in a controlled zone and immediately observe the new answer via your own resolver.
  • You can show an audit history of changes with timestamps and before/after snapshots.

Implementation Hints

  • Start only in a lab zone. Updates are powerful and easy to misuse.
  • Make prerequisites explicit and log them; silent overwrites are operationally dangerous.

Learning milestones

  1. Simple add/remove works → you understand UPDATE opcode basics
  2. Prerequisites enforced → you understand atomic update semantics
  3. Auditability added → you understand why ops teams fear “silent DNS edits”

Project 33: Resolver Observability Suite (Metrics + Trace Viewer)

  • File: LEARN_DNS.md
  • Main Programming Language: Go
  • Alternative Programming Languages: Rust, Python, TypeScript
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Observability / Operations
  • Software or Tool: DNS telemetry collector
  • Main Book: Release It! by Michael T. Nygard

What you’ll build: A small “control plane” for your resolver: structured logs, per-request hop traces, cache metrics (hit/miss, negative hits), and latency histograms.

Why it teaches DNS: Real DNS work is debugging. Observability forces you to explain where time is spent and why failures happen.

Core challenges you’ll face:

  • Defining a trace model for resolution steps (maps to resolution path understanding)
  • Metrics that reflect DNS realities (maps to operational semantics)
  • Log privacy concerns (maps to sensitive data considerations)

Key Concepts

  • RCODEs and error taxonomy: RFC 1035
  • Privacy motivation for minimization: RFC 9156 (context)

Difficulty: Intermediate Time estimate: 1–2 weeks Prerequisites: Any working resolver or forwarder

Real world outcome

  • You can explain with evidence why a query was slow or failed (which hop, which timeout).
  • You can verify caching reduces upstream traffic.

Implementation Hints

  • Make trace IDs first-class.
  • Provide redaction modes for domain names.

Learning milestones

  1. Metrics exist → you understand runtime behavior
  2. Traces are reliable → you understand multi-hop causality
  3. Debugging becomes systematic → you understand DNS ops realities

Project 34: Response Policy Zone (RPZ)-Style “Sinkhole” Resolver Mode

  • File: LEARN_DNS.md
  • Main Programming Language: Rust
  • Alternative Programming Languages: Go, Python, C++
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Security / Policy Enforcement
  • Software or Tool: DNS policy engine
  • Main Book: The Practice of Network Security Monitoring by Richard Bejtlich

What you’ll build: Add a policy layer to your resolver: override answers for blocked domains, return sinkhole IPs, and log hits with reason codes.

Why it teaches DNS: It forces you to understand where policy can be applied safely: before cache, after validation, before forwarding, etc.

Core challenges you’ll face:

  • Policy precedence relative to caching and DNSSEC (maps to correctness vs security)
  • Avoiding new failure modes (maps to operational stability)
  • Operator-friendly logs (maps to security operations)

Key Concepts

  • Forgery resilience mindset: RFC 5452
  • Security state reasoning (secure/insecure/bogus): RFC 4033–4035

Difficulty: Advanced Time estimate: 2–3 weeks Prerequisites: Working resolver and caching; ideally DNSSEC validator

Real world outcome

  • You can protect a test network by blocking known-bad domains and show resolver logs of blocked queries.
  • You can demonstrate the policy layer does not break normal resolution for non-blocked domains.

Implementation Hints

  • Keep rules data-driven and reloadable.
  • Decide and document whether policy applies to CNAME targets.

Learning milestones

  1. Block rules work → you understand hook points
  2. Policy + caching stable → you understand precedence and invariants
  3. Policy + DNSSEC reasoning → you understand how layers compose (or conflict)

Project 35: Comprehensive DNS Conformance Test Harness

  • File: LEARN_DNS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Rust, TypeScript
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Testing / Protocol Conformance
  • Software or Tool: DNS test harness
  • Main Book: Working Effectively with Legacy Code by Michael Feathers

What you’ll build: A black-box test harness that runs test cases against your DNS components and reports conformance: flags, RCODEs, caching behavior, EDNS, TCP fallback, and more.

Why it teaches DNS: DNS is edge-case heavy; you only “know” DNS when you can define and pass tests that encode semantics.

Core challenges you’ll face:

  • Deterministic tests for time-based caches (maps to testing with time)
  • Generating tricky cases (CNAME loops, wildcards, large answers) (maps to semantic coverage)
  • Actionable failure reports (maps to engineering maturity)

Key Concepts

  • Negative caching: RFC 2308
  • TCP fallback: RFC 7766
  • EDNS behavior: RFC 6891

Difficulty: Intermediate Time estimate: 1–2 weeks Prerequisites: At least one working DNS component

Real world outcome

  • You can run the harness and get a clear pass/fail report before and after changes.
  • You can add tests as you encounter real-world failures.

Implementation Hints

  • Separate case generation from assertions.
  • Build “golden traces” for iterative resolution.

Learning milestones

  1. Suite runs → you can encode DNS semantics into tests
  2. Edge cases covered → you understand where DNS breaks
  3. Regression safety → you understand how DNS software stays stable

Project 36: Capstone: Full Local DNS Stack (Authoritative + Recursive + Secure/Private Transports + Ops)

  • File: LEARN_DNS.md
  • Main Programming Language: Rust
  • Alternative Programming Languages: Go, C++, Elixir
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 4: Expert
  • Knowledge Area: Network Infrastructure / Security
  • Software or Tool: End-to-end DNS stack
  • Main Book: DNS and BIND by Cricket Liu & Paul Albitz

What you’ll build: A complete DNS stack you can run in a lab or home network: authoritative server for a test zone, recursive resolver with caching, DNSSEC validation, optional QNAME minimization, and client-facing endpoints that support classic DNS, DoT, and DoH—plus an observability dashboard.

Why it teaches DNS: It forces you to integrate every major DNS concept: hierarchy, serving, resolution, caching, transport, security, privacy, and operations.

Core challenges you’ll face:

  • Correct composition of features (cache + validation + policy + transports)
  • Debugging and observability across multiple services
  • Safe defaults and deterministic failure behavior

Key Concepts

  • Core DNS protocol: RFC 1034/1035
  • DNS over TCP: RFC 7766
  • EDNS(0): RFC 6891
  • DoT: RFC 7858
  • DoH: RFC 8484
  • DNSSEC: RFC 4033/4034/4035
  • QNAME minimization: RFC 9156

Difficulty: Expert Time estimate: 2–4 months Prerequisites: Most projects above, especially wire format, authoritative, resolver, caching, TCP, EDNS

Real world outcome

  • You can point real devices at your stack and resolve names reliably.
  • You can show encrypted upstream DNS traffic, validated responses, and measurable cache effectiveness.
  • You can demonstrate controlled failures (upstream outage, signature failure) and show deterministic behavior.

Implementation Hints

  • Build as separate processes first, then decide whether to merge.
  • Treat configuration and observability as first-class deliverables.

Learning milestones

  1. Authoritative + recursive works → you understand DNS end-to-end
  2. TCP/EDNS/DoT/DoH integrated → you understand modern transport realities
  3. DNSSEC + privacy hardening + ops maturity → you understand DNS as infrastructure

Project Comparison Table

# Project Difficulty Time Depth Best For
1 DNS Query Analyzer Beginner Weekend High Understanding wire format
2 Build Your Own dig Clone Intermediate 1 week High DNS client basics
3 Recursive DNS Resolver (From Root Servers) Advanced 1-2 weeks Very High DNS hierarchy
4 Authoritative DNS Server Advanced 2-3 weeks High Running DNS
5 DNS Caching Resolver Advanced 2 weeks High Performance
6 DNS Sinkhole / Ad Blocker (Pi-hole Clone) Advanced 2 weeks High Ad blocking, practical use
7 Reverse DNS Lookup Tool Intermediate 1 week Medium PTR records
8 DNS-over-HTTPS (DoH) Client Intermediate 1 week High DNS privacy
9 DNS-over-TLS (DoT) Client Intermediate 1 week High DNS privacy
10 Local DNS Proxy with Encryption Advanced 2 weeks High Network-wide privacy
11 DNSSEC Validator Expert 3-4 weeks Very High DNS security
12 DNS Zone Transfer Tool (AXFR) Intermediate 1 week High DNS replication
13 Dynamic DNS (DDNS) Client Intermediate 1 week Medium Practical utility
14 DNS Query Logger and Analyzer Intermediate 2 weeks High Security monitoring
15 DNS Load Balancer Advanced 2-3 weeks High Traffic management
16 Authoritative DNS Server with DNSSEC Signing Master 4-6 weeks Very High Cryptographic DNS
17 Complete DNS Infrastructure Stack (Capstone) Master 2-3 months Very High Full integration
18 DNS Wire-Format Inspector Intermediate Weekend High Binary parsing fundamentals
19 Minimal “dig” Clone (UDP Stub Resolver) Intermediate Weekend Medium Query construction
20 Zone File Parser & Linter Intermediate 1-2 weeks Medium-High Zone authoring
21 Minimal Authoritative DNS Server (UDP) Advanced 2-3 weeks High Protocol semantics
22 Iterative Recursive Resolver Advanced 1 month+ Very High Delegation traversal
23 Caching Resolver with Negative Caching Advanced 2-4 weeks Very High Cache correctness
24 DNS over TCP and Truncation Handling Advanced 2-3 weeks High Transport protocols
25 EDNS(0) Capability and UDP Payload Negotiation Advanced 1-2 weeks High Protocol extensibility
26 QNAME Minimization Expert 2-4 weeks Very High Privacy hardening
27 DNS Cookies Support Expert 2-4 weeks High Anti-forgery security
28 DNS-over-TLS (DoT) Client + Forwarder Advanced 2-3 weeks High Secure transport
29 DNS-over-HTTPS (DoH) Client + Forwarder Advanced 2-3 weeks High HTTP encapsulation
30 DNSSEC Validator (Recursive Validation Mode) Expert 1-2 months Extremely High Cryptographic verification
31 AXFR Zone Transfer Client + Secondary Zone Store Advanced 2-4 weeks High Zone replication
32 Dynamic DNS Update Client (RFC 2136) + Audit Log Advanced 2-3 weeks Medium-High Change management
33 Resolver Observability Suite Intermediate 1-2 weeks Medium Operations/debugging
34 RPZ-Style “Sinkhole” Resolver Mode Advanced 2-3 weeks High Policy enforcement
35 DNS Conformance Test Harness Intermediate 1-2 weeks High Protocol testing
36 Full Local DNS Stack (Capstone) Expert 2-4 months Very High Complete infrastructure

Complete Beginner (From LEARN_DNS_DEEP_DIVE):

1 -> 2 -> 3 (Query Analyzer -> dig clone -> Recursive resolver) This path takes you from seeing DNS packets to understanding the full resolution process.

Protocol Foundations (From LEARN_DNS_PROJECTS):

18 -> 19 -> 21 -> 22 (Wire Inspector -> Stub Resolver -> Auth Server -> Iterative Resolver) This path builds deep understanding of DNS wire format and resolution mechanics from scratch.

Want Practical Tools:

2 -> 6 -> 13 -> 10 (dig -> Sinkhole -> DDNS -> Privacy Proxy) Build tools you’ll actually use daily.

Security Focused (Combined):

1 -> 11 -> 14 -> 16 -> 27 -> 30 (Analyzer -> DNSSEC Validator -> Logger -> DNSSEC Server -> Cookies -> Full Validation) Focus on DNS security from validation to implementation and anti-forgery.

Infrastructure/DevOps:

4 -> 5 -> 15 -> 17 (Auth Server -> Caching -> Load Balancer -> Full Stack) Learn to run DNS infrastructure.

Privacy-First Path:

26 -> 8 -> 9 -> 28 -> 29 (QNAME Minimization -> DoH Client -> DoT Client -> DoT Forwarder -> DoH Forwarder) Focus on DNS privacy at every layer.

Transport & Protocol Mastery:

18 -> 24 -> 25 -> 28 -> 29 (Wire Format -> TCP Handling -> EDNS -> DoT -> DoH) Understand DNS across all transport mechanisms.

Operations & Observability:

20 -> 31 -> 32 -> 33 -> 35 (Zone Parser -> AXFR -> Dynamic Updates -> Observability -> Test Harness) Focus on DNS operations and tooling.

Maximum Learning (Deep Dive First):

Follow projects 1 through 17 from LEARN_DNS_DEEP_DIVE, then continue with 18 through 36 from LEARN_DNS_PROJECTS for comprehensive mastery.

Capstone Projects:

  • Project 17: Complete DNS Infrastructure Stack (from Deep Dive perspective)
  • Project 36: Full Local DNS Stack (from protocol-first perspective)

My Top Recommendations

Start Here: Project 3 or Project 22 (Recursive Resolver)

These are the single most educational DNS projects. After building one, you’ll truly understand how google.com becomes an IP address. The “Implement DNS in a Weekend” guide by Julia Evans makes this approachable.

Most Practical: Project 6 (DNS Sinkhole)

You’ll use this daily. Block ads and trackers for your entire network. It combines learning with immediate value.

Most Impressive: Project 16 or Project 30 (DNSSEC)

These put you in rare company. Few developers understand DNSSEC deeply enough to implement signing or full validation.

For Protocol Depth: Project 18 (DNS Wire-Format Inspector)

If you cannot decode a DNS packet yourself, everything else becomes guesswork. This removes the black box.


Summary: All Projects

# Project Name Main Language
1 DNS Query Analyzer Python
2 Build Your Own dig Clone Python
3 Recursive DNS Resolver (From Root Servers) Python
4 Authoritative DNS Server C
5 DNS Caching Resolver Python
6 DNS Sinkhole / Ad Blocker (Pi-hole Clone) Python
7 Reverse DNS Lookup Tool Python
8 DNS-over-HTTPS (DoH) Client Python
9 DNS-over-TLS (DoT) Client Python
10 Local DNS Proxy with Encryption Python
11 DNSSEC Validator Python
12 DNS Zone Transfer Tool (AXFR) Python
13 Dynamic DNS (DDNS) Client Python
14 DNS Query Logger and Analyzer Python
15 DNS Load Balancer Go
16 Authoritative DNS Server with DNSSEC Signing C
17 Complete DNS Infrastructure Stack (Capstone) Multiple
18 DNS Wire-Format Inspector C
19 Minimal “dig” Clone (UDP Stub Resolver) C
20 Zone File Parser & Linter Rust
21 Minimal Authoritative DNS Server (UDP) C
22 Iterative Recursive Resolver Rust
23 Caching Resolver with Negative Caching Rust
24 DNS over TCP and Truncation Handling C
25 EDNS(0) Capability and UDP Payload Negotiation Rust
26 QNAME Minimization Rust
27 DNS Cookies Support C
28 DNS-over-TLS (DoT) Client + Forwarder Go
29 DNS-over-HTTPS (DoH) Client + Forwarder Go
30 DNSSEC Validator (Recursive Validation Mode) Rust
31 AXFR Zone Transfer Client + Secondary Zone Store Go
32 Dynamic DNS Update Client (RFC 2136) + Audit Log Python
33 Resolver Observability Suite Go
34 RPZ-Style “Sinkhole” Resolver Mode Rust
35 DNS Conformance Test Harness Python
36 Full Local DNS Stack (Capstone) Rust

Essential Resources

Books

  • “DNS and BIND” by Paul Albitz & Cricket Liu - The DNS bible
  • “TCP/IP Illustrated, Volume 1” by W. Richard Stevens - Chapter 14 covers DNS
  • “TCP/IP Guide” by Charles M. Kozierok - Exhaustive DNS reference
  • “Serious Cryptography” by Jean-Philippe Aumasson - For DNSSEC cryptography
  • “Computer Networks” by Tanenbaum & Wetherall - Protocol foundations
  • “Designing Data-Intensive Applications” by Martin Kleppmann - For caching and distributed systems concepts
  • “The Practice of Network Security Monitoring” by Richard Bejtlich - DNS security monitoring
  • “Release It!” by Michael T. Nygard - Operational resilience patterns
  • “Design and Build Great Web APIs” by Mike Amundsen - For DoH HTTP semantics
  • “Working Effectively with Legacy Code” by Michael Feathers - Testing discipline

Online Resources

RFCs (The Real Specifications)

  • RFC 1034 - Domain Names: Concepts and Facilities
  • RFC 1035 - Domain Names: Implementation and Specification
  • RFC 2136 - Dynamic Updates in DNS
  • RFC 2308 - Negative Caching of DNS Queries
  • RFC 4033-4035 - DNSSEC (Introduction, Records, Protocol)
  • RFC 5155 - NSEC3
  • RFC 5452 - DNS Resilience Against Forgery
  • RFC 5936 - AXFR Zone Transfers
  • RFC 6891 - EDNS(0) Extension Mechanisms
  • RFC 7766 - DNS over TCP
  • RFC 7858 - DNS over TLS (DoT)
  • RFC 7873 - DNS Cookies
  • RFC 8484 - DNS over HTTPS (DoH)
  • RFC 8945 - TSIG Authentication
  • RFC 9018 - Anycast-friendly DNS Cookies
  • RFC 9156 - QNAME Minimization (obsoletes RFC 7816)

Tools for Testing


Merge Report

Source Files

| File | Projects | |——|———-| | LEARN_DNS_DEEP_DIVE.md | 17 projects | | LEARN_DNS_PROJECTS.md | 19 projects |

Total Projects: 36

Project Mapping

New # Project Name Source File
1 DNS Query Analyzer LEARN_DNS_DEEP_DIVE.md
2 Build Your Own dig Clone LEARN_DNS_DEEP_DIVE.md
3 Recursive DNS Resolver (From Root Servers) LEARN_DNS_DEEP_DIVE.md
4 Authoritative DNS Server LEARN_DNS_DEEP_DIVE.md
5 DNS Caching Resolver LEARN_DNS_DEEP_DIVE.md
6 DNS Sinkhole / Ad Blocker (Pi-hole Clone) LEARN_DNS_DEEP_DIVE.md
7 Reverse DNS Lookup Tool LEARN_DNS_DEEP_DIVE.md
8 DNS-over-HTTPS (DoH) Client LEARN_DNS_DEEP_DIVE.md
9 DNS-over-TLS (DoT) Client LEARN_DNS_DEEP_DIVE.md
10 Local DNS Proxy with Encryption LEARN_DNS_DEEP_DIVE.md
11 DNSSEC Validator LEARN_DNS_DEEP_DIVE.md
12 DNS Zone Transfer Tool (AXFR) LEARN_DNS_DEEP_DIVE.md
13 Dynamic DNS (DDNS) Client LEARN_DNS_DEEP_DIVE.md
14 DNS Query Logger and Analyzer LEARN_DNS_DEEP_DIVE.md
15 DNS Load Balancer LEARN_DNS_DEEP_DIVE.md
16 Authoritative DNS Server with DNSSEC Signing LEARN_DNS_DEEP_DIVE.md
17 Complete DNS Infrastructure Stack (Capstone) LEARN_DNS_DEEP_DIVE.md
18 DNS Wire-Format Inspector LEARN_DNS_PROJECTS.md
19 Minimal “dig” Clone (UDP Stub Resolver) LEARN_DNS_PROJECTS.md
20 Zone File Parser & Linter LEARN_DNS_PROJECTS.md
21 Minimal Authoritative DNS Server (UDP) LEARN_DNS_PROJECTS.md
22 Iterative Recursive Resolver LEARN_DNS_PROJECTS.md
23 Caching Resolver with Negative Caching LEARN_DNS_PROJECTS.md
24 DNS over TCP and Truncation Handling LEARN_DNS_PROJECTS.md
25 EDNS(0) Capability and UDP Payload Negotiation LEARN_DNS_PROJECTS.md
26 QNAME Minimization LEARN_DNS_PROJECTS.md
27 DNS Cookies Support LEARN_DNS_PROJECTS.md
28 DNS-over-TLS (DoT) Client + Forwarder LEARN_DNS_PROJECTS.md
29 DNS-over-HTTPS (DoH) Client + Forwarder LEARN_DNS_PROJECTS.md
30 DNSSEC Validator (Recursive Validation Mode) LEARN_DNS_PROJECTS.md
31 AXFR Zone Transfer Client + Secondary Zone Store LEARN_DNS_PROJECTS.md
32 Dynamic DNS Update Client (RFC 2136) + Audit Log LEARN_DNS_PROJECTS.md
33 Resolver Observability Suite LEARN_DNS_PROJECTS.md
34 RPZ-Style “Sinkhole” Resolver Mode LEARN_DNS_PROJECTS.md
35 DNS Conformance Test Harness LEARN_DNS_PROJECTS.md
36 Full Local DNS Stack (Capstone) LEARN_DNS_PROJECTS.md

Merge Notes

  • No projects were merged or deduplicated - all 36 projects were kept distinct per instructions
  • Projects 1-17 originate from LEARN_DNS_DEEP_DIVE.md (practical, tool-focused approach)
  • Projects 18-36 originate from LEARN_DNS_PROJECTS.md (protocol-first, systems approach)
  • Some conceptual overlap exists (e.g., dig clones, DNSSEC validators, caching resolvers) but each takes a different pedagogical approach and uses different primary languages
  • The two source files complement each other: Deep Dive emphasizes practical tools and Python, while Projects emphasizes protocol correctness and systems languages (C, Rust, Go)

Remember: DNS is the most used protocol you never think about. After these projects, you’ll think about it–and understand it completely.