feat: recursive DNS + DNSSEC + TCP fallback #17

Merged
razvandimescu merged 10 commits from feat/recursive-resolution into main 2026-03-28 10:03:47 +08:00
razvandimescu commented 2026-03-27 15:38:33 +08:00 (Migrated from github.com)

Summary

  • Recursive resolution: iterative RFC 1034 from root hints, CNAME chasing, referral following, A+AAAA glue, TLD priming (34 TLDs)
  • Full DNSSEC validation: chain-of-trust (RSA/SHA-256, ECDSA P-256, Ed25519), NSEC/NSEC3 authenticated denial, root KSK trust anchor
  • TCP fallback: UDP fail/truncation → automatic TCP retry, UDP auto-disable after 3 consecutive failures, IPv6 → TCP
  • Query minimization: RFC 7816 — root servers see TLD only, not full domain name
  • EDNS0: OPT pseudo-record, DO bit, 1232-byte payload (DNS Flag Day 2020)
  • Network resilience: works on ISPs blocking UDP:53 (tested on DIGI Romania), auto-detects and switches transport, resets on network change
  • 71 unit tests including TCP-only mock DNS server, 51 integration tests (4 suites), network probe script

Test plan

  • make all — fmt, clippy, audit, build, 71 unit tests pass
  • tests/integration.sh — 51 tests across 4 suites (recursive+DNSSEC, forward DoH, forward UDP, local zones+API)
  • tests/network-probe.sh — diagnoses transport availability per network
  • Tested on open network (UDP works) — 100-300ms cold, 0ms cached
  • Tested on restrictive network (DIGI, UDP:53 blocked) — TCP fallback resolves in 300-500ms
  • DNSSEC AD bit verified on cloudflare.com
  • Dogfooded as system DNS on macOS

🤖 Generated with Claude Code

## Summary - **Recursive resolution**: iterative RFC 1034 from root hints, CNAME chasing, referral following, A+AAAA glue, TLD priming (34 TLDs) - **Full DNSSEC validation**: chain-of-trust (RSA/SHA-256, ECDSA P-256, Ed25519), NSEC/NSEC3 authenticated denial, root KSK trust anchor - **TCP fallback**: UDP fail/truncation → automatic TCP retry, UDP auto-disable after 3 consecutive failures, IPv6 → TCP - **Query minimization**: RFC 7816 — root servers see TLD only, not full domain name - **EDNS0**: OPT pseudo-record, DO bit, 1232-byte payload (DNS Flag Day 2020) - **Network resilience**: works on ISPs blocking UDP:53 (tested on DIGI Romania), auto-detects and switches transport, resets on network change - **71 unit tests** including TCP-only mock DNS server, **51 integration tests** (4 suites), network probe script ## Test plan - [x] `make all` — fmt, clippy, audit, build, 71 unit tests pass - [x] `tests/integration.sh` — 51 tests across 4 suites (recursive+DNSSEC, forward DoH, forward UDP, local zones+API) - [x] `tests/network-probe.sh` — diagnoses transport availability per network - [x] Tested on open network (UDP works) — 100-300ms cold, 0ms cached - [x] Tested on restrictive network (DIGI, UDP:53 blocked) — TCP fallback resolves in 300-500ms - [x] DNSSEC AD bit verified on cloudflare.com - [x] Dogfooded as system DNS on macOS 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.