Project 5: DNS Resolver (Client-Side)
A DNS resolver that performs iterative queries and returns A and AAAA records.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Level 2: Intermediate |
| Time Estimate | Week |
| Main Programming Language | Python |
| Alternative Programming Languages | C, Go, Rust |
| Coolness Level | Level 3: Genuinely Clever |
| Business Potential | 2. The “Micro-SaaS / Pro Tool” |
| Prerequisites | See concepts below |
| Key Topics | Naming and Configuration Services (DNS, DHCP, mDNS), Transport and Ports (TCP and UDP) |
1. Learning Objectives
- Build and validate: A DNS resolver that performs iterative queries and returns A and AAAA records..
- Explain protocol behavior and verify it with a capture or trace.
- Handle edge cases and produce reproducible results.
2. All Theory Needed (Per-Concept Breakdown)
Naming and Configuration Services (DNS, DHCP, mDNS)
Fundamentals
Before a connection happens, a device needs two things: an address configuration and a name-to-address mapping. DHCP provides configuration: IP address, subnet mask, default gateway, and DNS servers. DNS provides name resolution: it turns a human-friendly name into IP addresses. On small local networks without an authoritative DNS server, mDNS and DNS-SD allow devices to discover services on the local link. These services are essential because users do not type IP addresses and devices do not manually configure themselves in modern networks.
Deep Dive
DNS is a hierarchical distributed database. When a client needs to resolve a name, it asks a recursive resolver (often provided by the ISP or a local router). The resolver performs iterative queries starting at the root, then the TLD, then the authoritative server for the zone. Responses are cached according to TTL values. This caching is why DNS queries can be fast, and also why changes can take time to propagate. DNS responses can arrive over UDP for small messages or TCP for larger responses or zone transfers. Understanding this distinction matters for debugging, since UDP truncation forces a TCP retry.
DHCP follows a discover-offer-request-acknowledge (DORA) exchange. A client with no address broadcasts a DHCPDISCOVER. A server replies with a DHCPOFFER. The client requests the offered address with DHCPREQUEST, and the server confirms with DHCPACK. Leases are time-limited and periodically renewed. This system allows dynamic reuse of addresses and centralized configuration. But it also introduces failure modes: multiple DHCP servers can fight, leases can expire if the server is unreachable, and clients can receive inconsistent options (like a wrong default gateway) that make the network appear partially broken.
mDNS and DNS-SD provide zero-configuration discovery. Instead of contacting a DNS server, devices send multicast queries to a well-known address on the local link. This allows discovery of printers, media devices, and local services without manual setup. The protocol reuses DNS message formats but changes the transport and scope. mDNS is powerful for home networks but can become noisy in larger environments. Understanding the scope and TTL settings for mDNS is essential when diagnosing why a device appears in a discovery list but is not reachable, or why service lists change frequently.
Naming and configuration services also intersect with security. DNS can be spoofed if you trust the wrong resolver or if a local attacker injects responses. DHCP can be abused by rogue servers. This is why managed networks often implement DHCP snooping and DNS security mechanisms. In home networks, the threat model is different, but the failure modes are similar. A misbehaving IoT device running a DHCP server can cause intermittent failures that look like random internet drops.
Finally, these services are the backbone of usability. When DNS or DHCP fails, users perceive that “the internet is down,” even if the physical link is fine. Your ability to build a DNS resolver or DHCP server from scratch is a demonstration that you truly understand how network configuration and naming work. It also makes you capable of implementing local overrides like DNS sinkholes, which are highly practical for security and ad-blocking.
How this fit on projects Projects 5-8, 10, and 16 are direct applications of DNS, DHCP, and mDNS.
Definitions & key terms
- Resolver: The client-side DNS component that asks questions.
- Recursive resolver: DNS server that walks the hierarchy on behalf of clients.
- TTL: Time-to-live for cached DNS answers.
- Lease: The time a DHCP address is valid.
- mDNS: Multicast DNS on a local link.
Mental model diagram
Client -> Resolver -> Root -> TLD -> Authoritative
^ cache TTLs at each step
How it works
- Client obtains an IP address and DNS server via DHCP.
- Client asks resolver for a name.
- Resolver walks the DNS hierarchy and caches answers.
- Local devices use mDNS for link-local discovery. Invariants: DNS is cached and hierarchical. Failure modes: rogue DHCP, stale DNS cache, mDNS storms.
Minimal concrete example
DNS query/response (text):
Query: A example.com
Answer: example.com -> 93.184.216.34 (TTL 86400)
Common misconceptions
- “DNS is always real-time.” It is cached by design.
- “DHCP only gives IP addresses.” It also provides gateway and DNS servers.
Check-your-understanding questions
- Why might a DNS change take hours to show up?
- What happens if a DHCP lease expires and the server is down?
Check-your-understanding answers
- Cached answers remain valid until TTL expires.
- The client may lose connectivity or fall back to a self-assigned address.
Real-world applications
- Local ad-blocking via DNS sinkholes.
- Zero-configuration printer discovery.
Where you will apply it
- Projects 5-8, 10, 16
References
- RFC 1034/1035 (DNS), RFC 2131 (DHCP)
- RFC 6762/6763 (mDNS, DNS-SD)
Key insights Naming and configuration are invisible until they fail, then everything fails.
Summary DNS and DHCP are the core control plane of a home network.
Homework/Exercises to practice the concept
- Trace a DNS lookup from your device to the authoritative server.
- Capture a DHCP DORA exchange and label each step.
Solutions to the homework/exercises
- Use
dig +traceand note each delegation. - Filter UDP ports 67 and 68 and identify discover, offer, request, ack.
Transport and Ports (TCP and UDP)
Fundamentals
The transport layer provides end-to-end communication between applications. TCP offers reliable, ordered delivery through acknowledgments, retransmission, and flow control. UDP provides minimal overhead without reliability guarantees, which makes it ideal for low-latency or simple query/response protocols like DNS. Ports are the addressing mechanism for applications. A network connection is identified by a 5-tuple: source IP, source port, destination IP, destination port, and protocol. Understanding how TCP and UDP differ is essential for building tools like ping-like diagnostics, port scanners, and proxies.
Deep Dive
TCP is a stateful protocol. It begins with a three-way handshake that establishes initial sequence numbers on both ends. Once established, each side maintains a sliding window of bytes that have been sent but not yet acknowledged. Retransmission occurs on timeout or after duplicate acknowledgments. Flow control uses the receiver’s advertised window to prevent buffer overflow, while congestion control reacts to signs of network congestion by reducing the sending rate. These behaviors are not just theoretical: they explain why a large file transfer can slow down after packet loss, and why a connection may stall if ACKs are filtered or delayed.
UDP is the opposite: it simply wraps application data with source and destination ports and a checksum. There is no handshake, no retransmission, and no ordering. This makes UDP great for short queries, live streaming, or gaming, where timeliness is more important than perfect delivery. But it also means that the application must handle loss, duplication, or reordering if those problems matter. This is why protocols like DNS and DHCP include their own retry logic and transaction IDs.
Ports are the multiplexing mechanism of the transport layer. A single IP address can host many services because each service listens on a different port. Clients use ephemeral ports chosen by the OS to distinguish their connections. Firewalls and NAT devices often make decisions based on ports and protocol state, which is why understanding TCP states (SYN_SENT, ESTABLISHED, FIN_WAIT) is crucial for debugging. For example, a firewall that drops inbound SYN packets but allows inbound ACKs can cause mysterious failures in connection setup while established connections continue to work.
Transport behavior is also shaped by MTU and fragmentation. TCP segments are sized to fit within the path MTU. If a segment is too large and fragmentation is blocked, the connection can stall in ways that appear random. UDP has no built-in recovery for lost fragments, which can make large UDP payloads unreliable. This is why many UDP-based protocols keep messages small or implement their own segmentation and reassembly.
When you build transport-layer tools, you are interacting with a state machine. A port scanner that uses TCP SYN packets is testing how a host responds to a state transition. A proxy server is managing two concurrent TCP state machines and relaying data between them. A VPN tunnel often runs over UDP or TCP and must handle reliability differently depending on the transport. The more you understand transport mechanics, the more precise your debugging and design choices become.
How this fit on projects Projects 2, 3, 9, 11, 17, and 19 depend directly on transport behavior.
Definitions & key terms
- 5-tuple: The identifiers of a transport flow.
- Handshake: TCP connection establishment.
- Window: Flow control mechanism for TCP.
- Ephemeral port: Temporary client port assigned by the OS.
Mental model diagram
Client Server
SYN --------------------> (listening)
SYN-ACK <------------------
ACK --------------------> (established)
How it works
- TCP establishes state via handshake.
- Data is sent with sequence numbers and ACKs.
- Loss triggers retransmission and window reduction.
- UDP sends without state; application handles retries if needed. Invariants: TCP guarantees order if the connection stays up. Failure modes: half-open connections, blocked SYNs, dropped ACKs.
Minimal concrete example
UDP request/response:
Client -> UDP:53 query id=0x1234
Server -> UDP:53 response id=0x1234
Common misconceptions
- “UDP is always faster.” It can be, but loss may negate benefits.
- “TCP guarantees delivery across the internet.” It only guarantees delivery within the connection’s lifetime.
Check-your-understanding questions
- Why does a TCP connection need both sequence and acknowledgment numbers?
- When would you choose UDP over TCP for a home network tool?
Check-your-understanding answers
- To track sent bytes and confirm receipt in order.
- For low-latency, small messages where retries are acceptable.
Real-world applications
- Reliable file transfer versus real-time streaming.
- Port scanning and service discovery.
Where you will apply it
- Projects 2, 3, 9, 11, 17, 19
References
- RFC 9293 (TCP), RFC 768 (UDP)
- “TCP/IP Illustrated, Vol 1” by Stevens - Ch. 11-16
Key insights Transport protocols are state machines; your tools must respect their state.
Summary TCP and UDP make different promises. Your designs must align with those promises.
Homework/Exercises to practice the concept
- List three application protocols that use UDP and why.
- Draw the TCP close sequence and label each side’s state.
Solutions to the homework/exercises
- DNS (small queries), NTP (time sync), VoIP (latency).
- FIN/ACK exchange with TIME_WAIT on the side that closes last.
3. Project Specification
3.1 What You Will Build
A DNS resolver that performs iterative queries and returns A and AAAA records.
Included:
- CLI tool with clear output
- Validation steps and logging
- Documentation of assumptions
Excluded:
- Production-grade performance tuning
- Full security hardening
3.2 Functional Requirements
- Core function: Implement the primary behavior described in the project goal.
- Observable output: Produce deterministic output comparable to the Real World Outcome.
- Error handling: Handle timeouts, invalid inputs, and unreachable hosts gracefully.
3.3 Non-Functional Requirements
- Performance: Complete typical tasks within a few seconds on a LAN.
- Reliability: Fail safely and clearly on errors.
- Usability: Provide concise CLI flags and helpful messages.
3.4 Example Usage / Output
$ ./resolve example.com
Query: A example.com
Answer: 93.184.216.34
Trace:
root -> .com -> example.com
Cache: stored for 86400 seconds
3.5 Data Formats / Schemas / Protocols
Protocols: Naming and Configuration Services (DNS, DHCP, mDNS), Transport and Ports (TCP and UDP).
3.6 Edge Cases
- Target unreachable or timing out
- Malformed or unexpected responses
- Multiple interfaces or subnets
3.7 Real World Outcome
$ ./resolve example.com
Query: A example.com
Answer: 93.184.216.34
Trace:
root -> .com -> example.com
Cache: stored for 86400 seconds
3.7.1 How to Run (Copy/Paste)
- Build:
make(or create a virtual environment as needed) - Run:
./P05-dns-resolver-client - Config: update any constants in a config file or flags
- Working directory: project root
3.7.2 Golden Path Demo (Deterministic)
Run against a known local target and compare with the expected output.
3.7.3 If CLI: provide an exact terminal transcript
$ ./resolve example.com
Query: A example.com
Answer: 93.184.216.34
Trace:
root -> .com -> example.com
Cache: stored for 86400 seconds
4. Solution Architecture
4.1 High-Level Design
CLI Input -> Core Engine -> Output/Logs
4.2 Key Components
| Component | Responsibility | Key Decisions |
|---|---|---|
| CLI Parser | Parse flags and inputs | Keep interface minimal |
| Core Engine | Protocol logic and state | Keep deterministic timing |
| Output/Logs | Present results and errors | Use consistent formatting |
4.4 Data Structures (No Full Code)
Request:
- target
- protocol fields
Response:
- status
- timing
State:
- retries
- cache entries
5. Implementation Guide
5.1 Development Environment Setup
- Ensure required tools (tcpdump, dig, ip) are installed.
- Use elevated privileges where raw sockets are required.
5.2 Project Structure
project/
README.md
docs/
src/
tests/
data/
5.3 The Core Question You’re Answering
“How does a name become an IP address without a single global database?”
5.4 Concepts You Must Understand First
- DNS message format
- How are questions and answers encoded?
- Book Reference: “TCP/IP Illustrated, Vol 1” - Ch. 18
- Recursive vs iterative resolution
- What does a resolver actually do step-by-step?
- Book Reference: “Computer Networks” - Ch. 7
- UDP transport
- Why does DNS typically use UDP?
- Book Reference: “TCP/IP Illustrated, Vol 1” - Ch. 11
5.5 Questions to Guide Your Design
- Resolver strategy
- How will you choose root servers?
- When do you retry over TCP?
- Caching
- Where and how will you store TTL-based cache entries?
5.6 Thinking Exercise
Name resolution trace
Write the sequence of DNS queries from root to authoritative for example.com.
Questions to answer:
- What records are returned at each step?
- Which responses are cached?
5.7 The Interview Questions They’ll Ask
- “What is the difference between recursive and iterative DNS?”
- “Why does DNS use UDP by default?”
- “What happens when a DNS response is truncated?”
- “How does TTL affect caching and consistency?”
- “How would you detect DNS poisoning on a LAN?”
5.8 Hints in Layers
Hint 1: Start with a single record type Support A records first, then add AAAA.
Hint 2: Use known root hints Start with a root server list and iterate.
Hint 3: Pseudocode outline
- build DNS query
- send to root server
- follow referrals until authoritative
- return final answer
- cache by TTL
Hint 4: Verification
Compare your output to dig +trace example.com.
5.9 Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| DNS basics | “TCP/IP Illustrated, Vol 1” | Ch. 18-19 |
| DNS at scale | “Computer Networks” | Ch. 7 |
| UDP transport | “TCP/IP Illustrated, Vol 1” | Ch. 11 |
5.10 Implementation Phases
- Establish core protocol I/O and a minimal success path.
- Add parsing, validation, and timeouts.
- Add logging, metrics, and polish for output.
5.11 Key Implementation Decisions
- Which interface and capture point provides visibility?
- What timeout and retry strategy balances speed and accuracy?
- How will results be validated against reference tools?
6. Testing Strategy
6.1 Test Categories
- Unit: parsing and validation logic
- Integration: protocol exchange with a real device
- System: full run with reference tools
6.2 Critical Test Cases
- Successful request/response path
- Timeout and retry behavior
- Invalid or unexpected input handling
6.3 Test Data
- Local gateway IP and a known reachable host
- A non-routable IP to trigger timeouts
7. Common Pitfalls & Debugging
7.1 Frequent Mistakes
Problem 1: “Stuck in referral loop”
- Why: Not following NS records correctly.
- Fix: Parse authority and additional sections carefully.
- Quick test: Compare with
dig +traceoutput.
Problem 2: “Some domains fail”
- Why: No TCP fallback on truncation.
- Fix: Detect truncation flag and retry over TCP.
- Quick test: Query a DNSSEC-signed domain with large responses.
7.2 Debugging Strategies
- Capture traffic with tcpdump or Wireshark.
- Compare against a known-good tool.
- Log timestamps and retry logic.
7.3 Performance Traps
- Excessive retries causing long runtimes.
- Inefficient parsing under high packet rates.
8. Extensions & Challenges
8.1 Beginner Extensions
- Add basic configuration flags for interface and timeout.
- Improve output formatting and sorting.
8.2 Intermediate Extensions
- Add caching or state persistence.
- Add CSV or JSON output export.
8.3 Advanced Extensions
- Add concurrency with careful rate limiting.
- Add visualization or integration with a dashboard.
9. Real-World Connections
9.1 Industry Applications
- Network diagnostics and troubleshooting
- Security monitoring and policy enforcement
9.2 Related Open Source Projects
- tcpdump / Wireshark
- nmap / dnsmasq / unbound (as applicable)
9.3 Interview Relevance
- Explaining protocol behavior
- Diagnosing failures by layer
10. Resources
10.1 Essential Reading
| Topic | Book | Chapter |
|---|---|---|
| DNS basics | “TCP/IP Illustrated, Vol 1” | Ch. 18-19 |
| DNS at scale | “Computer Networks” | Ch. 7 |
| UDP transport | “TCP/IP Illustrated, Vol 1” | Ch. 11 |
10.2 Video Resources
- Wireshark or tcpdump walkthroughs (search for recent tutorials)
- Vendor or RFC explainers for the relevant protocol
10.3 Tools & Documentation
- RFCs for the protocols used in this project
man tcpdump,man ip,man ss
10.4 Related Projects in This Series
- Project 2: Build Your Own ping Utility
- Project 6: DHCP Client
- Project 7: Simple DNS Server (Authoritative)
- Project 8: DHCP Server
- Project 9: Port Scanner
- Project 10: DNS Sinkhole (Pi-hole Style)
- Project 11: Simple HTTP Server
- Project 14: Software Router with NAT
- Project 16: mDNS/Bonjour Service Discovery
- Project 17: HTTP Proxy Server
- Project 19: Simple VPN Server
- Project 20: Complete Home Network Stack (Capstone)