Why DNS Cache Hardening Matters for Self-Hosted Infrastructure
Every DNS query your network makes passes through a recursive resolver. That resolver caches answers to speed up subsequent lookups — but the cache itself is a high-value attack surface. DNS cache poisoning attacks can redirect your users to malicious servers, intercept encrypted traffic, and silently compromise your entire network.
A hardened DNS resolver mitigates these risks through multiple defense layers: DNSSEC validation, QNAME minimization, cache segregation, source port randomization, and aggressive cache-ttl policies. The three most mature open-source recursive resolvers — Unbound, BIND 9, and Knot Resolver — each take different approaches to cache security.
This guide compares their hardening features side by side and provides production-ready Docker deployment configurations so you can deploy a hardened resolver in minutes.
Understanding DNS Cache Poisoning
DNS cache poisoning exploits the fact that DNS was designed without authentication. An attacker who can spoof a DNS response before the legitimate reply arrives can inject false records into your resolver’s cache. The classic Kaminsky attack (2008) demonstrated how attackers could poison any record by flooding the resolver with forged responses during the brief window between query and response.
Modern resolvers defend against this through several mechanisms:
- DNSSEC validation — cryptographically verifies answer authenticity
- Source port randomization — makes it harder to guess the query ID + port combination
- QNAME minimization — sends only the minimum necessary query to upstream servers, reducing information leakage
- Cache-minimize mode — avoids caching unnecessary referral data that could be poisoned
- Aggressive use of NSEC/NSEC3 — securely proves non-existence of domains, preventing wildcard spoofing
- Strict cache TTL enforcement — prevents attackers from keeping poisoned entries alive
Unbound: Security-First DNS Resolver
Unbound (4,469 GitHub stars, last updated April 2026) was designed from the ground up with security as its primary goal. Developed by NLnet Labs and maintained by the OSS community, it is the default recursive resolver on OpenBSD and widely recommended for hardened DNS deployments.
Cache Hardening Features
Unbound’s cache hardening configuration options are among the most comprehensive of any open-source resolver:
| |
Key strengths of Unbound’s approach:
harden-*flags — seven separate hardening toggles that independently validate and restrict cache behaviorcache-minimize— prevents the resolver from caching unnecessary NS/A records that could be poisonedaggressive-nsec— uses DNSSEC proof-of-nonexistence to answer negative queries from cache, reducing upstream queriesqname-minimisation-strict— sends only the rightmost label to root servers, progressively revealing more as needed
Docker Deployment
| |
BIND 9: The Battle-Tested Resolver
BIND 9 is maintained by the Internet Systems Consortium (ISC). The GitHub mirror shows 739 stars but is archived — primary development moved to GitLab. BIND 9 has been the reference DNS implementation since 1998 and ships with most Linux distributions.
Cache Hardening Features
BIND 9’s hardening options focus on DNSSEC validation and query/response control:
| |
BIND 9’s approach differs from Unbound:
dnssec-validation auto— automatically manages trust anchors, similar to Unboundminimal-responses— reduces the amount of data in responses, limiting poisoning surfaceminimal-any— prevents ANY query amplification attacksrate-limit— built-in response rate limiting (RRL) to mitigate amplification- BIND 9 does not have a direct equivalent to Unbound’s
aggressive-nsecorcache-minimizeflags
The resolver’s strength lies in its maturity and the extensive rate-limit block, which provides fine-grained control over response rates per client, per domain, and globally.
Docker Deployment
| |
Knot Resolver: Modern and Extensible
Knot Resolver (434 GitHub stars, last updated April 2026) is developed by CZ.NIC, the Czech national domain registry operator. It is built on top of the Knot DNS library and uses the Lua scripting language for policy modules — making it the most programmable of the three resolvers.
Cache Hardening Features
Knot Resolver’s approach is module-based, allowing you to compose security features as Lua policy modules:
| |
Knot Resolver’s unique advantages:
- Lua policy modules — write custom security policies in Lua, enabling fine-grained control over every query and response
- DNSSEC enabled by default — unlike Unbound and BIND 9 which require explicit configuration
- QNAME minimization enabled by default — another security feature active out of the box
policy.TLS_FORWARD— forwards all queries over TLS, protecting against upstream interception- Built-in RPZ-style filtering — deny specific domains, block categories, and redirect queries via policy rules
Docker Deployment
| |
Feature Comparison Table
| Feature | Unbound | BIND 9 | Knot Resolver |
|---|---|---|---|
| DNSSEC Validation | ✅ auto-trust-anchor | ✅ dnssec-validation auto | ✅ Enabled by default |
| QNAME Minimization | ✅ qname-minimisation | ✅ qname-minimization (9.17+) | ✅ Enabled by default |
| Aggressive NSEC | ✅ aggressive-nsec | ❌ Not supported | ✅ Via policy module |
| Cache Minimize | ✅ cache-minimize | ❌ Not supported | ⚠️ Partial via modules |
| Harden Glue | ✅ harden-glue | ⚠️ Implicit | ⚠️ Via policy |
| Rate Limiting | ✅ ratelimit | ✅ rate-limit (RRL) | ✅ policy.RATE_LIMIT |
| Strict Hardening | ✅ 7 harden-* flags | ⚠️ Limited | ✅ Via policy modules |
| TLS Upstream | ✅ forward-tls-upstream | ❌ Requires Stunnel | ✅ policy.TLS_FORWARD |
| Custom Policies | ❌ No scripting | ❌ No scripting | ✅ Lua modules |
| Docker Image | ✅ mvance/unbound | ✅ ubuntu/bind9 | ✅ cznic/knot-resolver |
| Default Security | ⚠️ Requires config | ⚠️ Requires config | ✅ Secure defaults |
| GitHub Stars | 4,469 | 739 (mirror) | 434 |
Performance and Resource Comparison
| Metric | Unbound | BIND 9 | Knot Resolver |
|---|---|---|---|
| Memory (idle) | ~50 MB | ~100 MB | ~80 MB |
| Memory (heavy cache) | ~200 MB | ~500 MB | ~300 MB |
| Queries/sec (single core) | ~250K | ~150K | ~200K |
| Configuration language | YAML-style | BIND9 zone format | Lua |
| Learning curve | Low | Medium | Medium-High |
Unbound is the lightest and fastest for pure DNS resolution. BIND 9 uses the most memory but offers the deepest feature set for complex deployments. Knot Resolver sits in the middle, trading some raw performance for programmability.
Which Resolver Should You Choose?
Choose Unbound if:
- You want the most hardened resolver with the least configuration effort
- You need maximum cache hardening flags out of the box
- Resource efficiency is a priority (low memory footprint)
- You are deploying on OpenBSD, pfSense, or OPNsense (it is the default)
Choose BIND 9 if:
- You need authoritative and recursive DNS in a single process
- Your environment requires RRL (Response Rate Limiting) with fine-grained controls
- You are already managing BIND 9 authoritative zones and want to consolidate
- Your organization has existing BIND 9 expertise
Choose Knot Resolver if:
- You want programmable security policies via Lua scripting
- You need DNSSEC and QNAME minimization enabled by default
- You want built-in TLS forwarding without external dependencies
- You need RPZ-style filtering with custom logic
For most self-hosted homelab users, Unbound offers the best balance of security, simplicity, and performance. Its seven hardening flags are the most comprehensive defense against cache poisoning available in any open-source resolver.
FAQ
What is DNS cache poisoning and how does it work?
DNS cache poisoning is an attack where a forged DNS response is injected into a resolver’s cache, causing the resolver to return incorrect IP addresses for domain names. The attacker sends a spoofed response that arrives before the legitimate answer from the authoritative server. If the resolver accepts the forged response, it caches the false record and serves it to all subsequent clients, redirecting them to attacker-controlled servers.
Is DNSSEC enough to prevent cache poisoning?
DNSSEC is the single most effective defense against cache poisoning because it cryptographically validates every answer. However, it is not sufficient on its own. DNSSEC only protects zones that are signed (most major TLDs and domains are, but not all). Cache hardening features like QNAME minimization, aggressive NSEC, and rate limiting provide additional layers of defense that protect against attacks even when DNSSEC validation is not possible.
Can I use multiple hardened resolvers together?
Yes. A common architecture is to run Unbound as the primary resolver with BIND 9 or Knot Resolver as a secondary/failover resolver. You can also stack them — for example, use Knot Resolver with TLS forwarding to upstream Unbound instances, creating a defense-in-depth pipeline. Docker Compose makes this topology straightforward to deploy.
How often should I rotate DNSSEC trust anchors?
DNSSEC trust anchors (root keys) are automatically managed by all three resolvers through RFC 5011 automatic key rollover. You should still periodically verify that the root key file is valid. In Unbound, check /var/lib/unbound/root.key. In BIND 9, check managed-keys-directory. In Knot Resolver, trust anchors are managed internally and updated automatically.
Does running a hardened resolver slow down DNS resolution?
The performance impact is negligible. DNSSEC validation adds approximately 5-15ms per query (only for the first lookup — subsequent queries are served from cache). QNAME minimization may add one extra round-trip for some queries. Aggressive NSEC actually improves performance for negative queries by answering them from cache instead of querying upstream. In practice, a properly configured hardened resolver is indistinguishable in speed from a non-hardened one for end users.
What is QNAME minimization and why does it matter?
QNAME minimization reduces the amount of query information sent to upstream DNS servers. Instead of sending the full domain name (e.g., mail.example.com) to the root server, the resolver sends only the top-level domain (com) and progressively reveals more labels as it descends the DNS hierarchy. This prevents upstream servers from learning your full query patterns, which improves privacy and reduces the attack surface for targeted poisoning attacks.
For related reading, see our PowerDNS vs BIND 9 vs NSD vs Knot authoritative DNS guide and DNSSEC management with OpenDNSSEC vs Knot DNS vs BIND.