Back to Projects

dnsr

Iterative, DNSSEC-validating DNS resolver written from scratch in Go, walking the hierarchy from the root servers and serving answers over UDP, TCP, and DNS over TLS 1.3.

Architecture Overview

Stdlib-only Go split into wire (message parse/build and DNSSEC record formats), resolver (iterative resolution, answer/delegation/key caches, DNSSEC validation), and server (UDP/TCP/DoT listeners, ACL, rate limit) packages, with a dnsr CLI and a small dnsq test client.

Key Challenges

Following referrals, glueless delegations, CNAME chains, and TC-to-TCP fallback from the 13 root hints while building a DNSSEC chain of trust that classifies every answer as secure, insecure, or bogus; tested offline with a loopback DNS hierarchy signed with real ECDSA keys, including hostile servers that send forged replies and poisoned glue.

Security Considerations

Defends against off-path spoofing, cache poisoning, poisoned glue, open-resolver amplification, NXNSAttack-style resource exhaustion, and malformed packets via strict reply matching, bailiwick checks, bounded caches and glueless lookups, compression-jump limits, and escaping of untrusted names before printing; bogus DNSSEC answers return SERVFAIL.

Future Improvements

Planned: NSEC/NSEC3 authenticated denial of existence, negative caching (RFC 2308), IPv6 transport, parallel queries with RTT-based server selection, DNS Cookies, and DNS over HTTPS.

Technical Impact

  • Built an iterative DNS resolver in stdlib-only Go, hand-encoding the RFC 1035 wire format with name compression, EDNS(0), and 11 record types including DS, DNSKEY, and RRSIG.
  • Implemented DNSSEC chain-of-trust validation from the IANA root KSKs through DS and DNSKEY to each answer's RRSIG, supporting RSA, ECDSA P-256/P-384, and Ed25519.
  • Hardened resolution against cache poisoning with crypto-random query IDs, 0x20 case randomisation, bailiwick checks, glue filtering, and QNAME minimisation (RFC 9156).
  • Built a recursive server over UDP, TCP, and TLS 1.3-only DoT with an access list, per-client token-bucket rate limiting, and in-flight caps, verified by 34 offline tests against a signed fake DNS hierarchy and 1M fuzzed packets with zero panics.