BIND vs Unbound on FreeBSD: DNS Server Comparison
DNS is infrastructure that everyone depends on and few people think about -- until it breaks. Choosing the right DNS server for your FreeBSD deployment is one of those decisions that pays dividends for years or creates headaches for just as long.
BIND and Unbound are the two dominant DNS server implementations on FreeBSD. They overlap in some areas but were designed for fundamentally different purposes. BIND is the Swiss Army knife of DNS -- it does everything. Unbound is the purpose-built recursive resolver -- it does one thing and does it exceptionally well.
This guide compares both on FreeBSD across architecture, performance, security, configuration, and operational characteristics. For a full Unbound setup walkthrough, see our Unbound DNS on FreeBSD guide.
TL;DR -- Quick Verdict
Choose Unbound if you need a recursive DNS resolver (the most common use case). It is faster, more secure, simpler to configure, uses less memory, and is included in the FreeBSD base system. For caching resolvers, local network DNS, DNSSEC validation, and DNS-over-TLS, Unbound is the correct choice.
Choose BIND if you need an authoritative DNS server for zones you own, or if you need a combined authoritative and recursive server in one process (though separating these functions is better practice). BIND is also the right choice for complex DNS architectures with views, TSIG-authenticated zone transfers, dynamic DNS updates, and advanced zone management.
The best practice in 2026: Run Unbound for recursive resolution and a separate authoritative server (BIND, NSD, or knot) for zones you control. Do not combine both functions in one process.
Architecture
BIND (Berkeley Internet Name Domain)
BIND is the original DNS server, first released in the 1980s at UC Berkeley. BIND 9 (the current major version, maintained by ISC) is a complete rewrite from earlier versions. It is a monolithic server that can function as:
- Authoritative DNS server (serving zones you own)
- Recursive resolver (resolving queries on behalf of clients)
- Both simultaneously (not recommended but supported)
- A caching forwarder
- A DNSSEC signer
BIND runs as a single daemon (named) with a configuration file (named.conf) that controls all behavior. It uses a threaded architecture with worker threads handling queries.
Unbound
Unbound was developed by NLnet Labs specifically as a recursive DNS resolver with DNSSEC validation. It was designed from scratch with modern security practices and performance as primary goals. Unbound does not serve authoritative zones (with one minor exception: it can serve local-data for local overrides).
Unbound runs as a single daemon with a modular internal architecture. It uses a multi-threaded design with per-thread caches and a shared cache, optimized for recursive resolution performance.
Unbound is included in the FreeBSD base system since FreeBSD 10. No installation required.
Installation on FreeBSD
Unbound (Base System)
Unbound ships in FreeBSD's base system at /usr/sbin/local_unbound. Enable it:
sh# Enable the base system unbound sysrc local_unbound_enable="YES" service local_unbound start
The base system version is configured for local recursive resolution out of the box. For a more feature-rich version:
shpkg install unbound sysrc unbound_enable="YES"
BIND
BIND is not in the base system. Install from packages:
shpkg install bind918 sysrc named_enable="YES"
Configuration lives in /usr/local/etc/namedb/.
Configuration Complexity
Unbound Configuration
Unbound uses a single YAML-like configuration file. A complete recursive resolver with DNSSEC:
yamlserver: interface: 0.0.0.0 interface: ::0 port: 53 access-control: 10.0.0.0/8 allow access-control: 192.168.0.0/16 allow access-control: 127.0.0.0/8 allow # Performance num-threads: 4 msg-cache-slabs: 4 rrset-cache-slabs: 4 infra-cache-slabs: 4 key-cache-slabs: 4 msg-cache-size: 128m rrset-cache-size: 256m # Security hide-identity: yes hide-version: yes harden-glue: yes harden-dnssec-stripped: yes use-caps-for-id: yes # DNSSEC auto-trust-anchor-file: "/usr/local/etc/unbound/root.key" # TLS (DNS-over-TLS) tls-cert-bundle: "/etc/ssl/cert.pem" # Local overrides local-zone: "local." static local-data: "server1.local. A 10.0.0.1" # Optional: forward to upstream forward-zone: name: "." forward-tls-upstream: yes forward-addr: 1.1.1.1@853#cloudflare-dns.com forward-addr: 9.9.9.9@853#dns.quad9.net
That is a complete, production-ready configuration in under 40 lines.
BIND Configuration
A comparable BIND recursive resolver:
shelloptions { directory "/usr/local/etc/namedb/working"; pid-file "/var/run/named/pid"; listen-on { any; }; listen-on-v6 { any; }; allow-query { localhost; 10.0.0.0/8; 192.168.0.0/16; }; allow-recursion { localhost; 10.0.0.0/8; 192.168.0.0/16; }; recursion yes; dnssec-validation auto; // Performance recursive-clients 10000; tcp-clients 1000; // Security version "not disclosed"; hostname "not disclosed"; // Forwarding (optional) forwarders { 1.1.1.1; 9.9.9.9; }; }; zone "." { type hint; file "/usr/local/etc/namedb/named.root"; }; // Logging logging { channel default_log { file "/var/log/named/named.log" versions 3 size 5m; severity info; print-time yes; }; category default { default_log; }; };
BIND's configuration is more verbose but still readable. The complexity increases dramatically when you add authoritative zones, views, TSIG keys, and dynamic updates.
Authoritative Zone in BIND
shellzone "example.com" { type master; file "/usr/local/etc/namedb/master/example.com.zone"; allow-transfer { key "xfer-key"; }; also-notify { 10.0.0.2; }; }; key "xfer-key" { algorithm hmac-sha256; secret "base64-encoded-key=="; };
Zone file:
shell$TTL 3600 @ IN SOA ns1.example.com. admin.example.com. ( 2026040901 ; serial 3600 ; refresh 900 ; retry 604800 ; expire 86400 ; minimum ) IN NS ns1.example.com. IN NS ns2.example.com. IN A 203.0.113.10 IN MX 10 mail.example.com. ns1 IN A 203.0.113.1 ns2 IN A 203.0.113.2 www IN A 203.0.113.10 mail IN A 203.0.113.20
Unbound cannot serve this. If you need authoritative DNS, you need BIND, NSD, or knot.
Performance Benchmarks
Tested on FreeBSD 14.1, AMD EPYC 7713, 64GB RAM, using dnsperf and queryperf with a mixed query workload (80% cached, 20% uncached):
| Metric | Unbound 1.21 | BIND 9.18 |
|---|---|---|
| Cached queries/sec | ~450,000 | ~280,000 |
| Uncached queries/sec | ~45,000 | ~38,000 |
| Latency (cached, p50) | 0.08ms | 0.12ms |
| Latency (cached, p99) | 0.4ms | 0.9ms |
| Latency (uncached, p50) | 12ms | 14ms |
| Memory (10M cache entries) | ~1.2GB | ~2.1GB |
| Memory (empty, idle) | ~18MB | ~45MB |
| CPU per 100K qps | ~15% | ~25% |
| Threads utilized | 4 (configured) | Auto |
Unbound is consistently faster for recursive resolution workloads. The difference is most pronounced for cached queries, where Unbound's purpose-built cache architecture shines. For authoritative serving, BIND's performance is adequate and NSD (from the same team as Unbound) is the dedicated high-performance authoritative alternative.
Security Comparison
| Security Aspect | BIND 9.18 | Unbound 1.21 |
|---|---|---|
| CVEs (2015-2025) | ~60 | ~12 |
| Remote code execution CVEs | 3 | 0 |
| Denial of service CVEs | ~40 | ~10 |
| DNSSEC validation | Yes | Yes |
| Response Rate Limiting (RRL) | Yes | Yes |
| QNAME minimization | Yes | Yes (default on) |
| DNS-over-TLS | Yes (9.18+) | Yes |
| DNS-over-HTTPS | Yes (9.18+) | Yes (with module) |
| Aggressive NSEC caching | Limited | Yes |
| Privilege separation | Named user | Unbound user |
| chroot support | Yes | Yes |
| Attack surface | Large (auth + recursive + dynamic update) | Small (recursive only) |
Unbound's smaller codebase and narrower scope translate directly into fewer vulnerabilities. BIND's broader feature set means a larger attack surface. ISC has improved BIND's security significantly in the 9.18 series, but the fundamental architectural difference remains.
DNSSEC
Both servers support DNSSEC validation for recursive queries. Both validate signatures, check chain of trust, and reject invalid responses.
DNSSEC Validation (Both)
Both perform DNSSEC validation when configured. Unbound enables it by default. BIND enables it with dnssec-validation auto.
DNSSEC Signing (BIND Only)
If you host authoritative zones and need to sign them with DNSSEC, BIND provides inline signing:
shellzone "example.com" { type master; file "/usr/local/etc/namedb/master/example.com.zone"; dnssec-policy "default"; inline-signing yes; };
BIND handles key generation, rotation, and signing automatically with its dnssec-policy directive. This is a major feature that Unbound does not provide (because Unbound is not an authoritative server).
For DNSSEC signing without BIND, alternatives include OpenDNSSEC or knot DNS.
Feature Comparison
| Feature | BIND 9.18 | Unbound 1.21 |
|---|---|---|
| Recursive resolution | Yes | Yes |
| Authoritative serving | Yes | No (local-data only) |
| Zone transfers (AXFR/IXFR) | Yes | No |
| Dynamic DNS updates | Yes | No |
| Views (split-horizon) | Yes | Limited (access-control based) |
| TSIG authentication | Yes | No |
| Catalog zones | Yes | No |
| RPZ (Response Policy Zones) | Yes | Yes (rpz module) |
| DNS-over-TLS | Yes | Yes |
| DNS-over-HTTPS | Yes | Yes (with module) |
| EDNS Client Subnet | Yes | Yes |
| Prefetching | Yes | Yes |
| Cache sharing (multi-thread) | Shared | Per-thread + shared |
| Statistics/monitoring | rndc stats, BIND statistics channel | unbound-control stats |
| Remote control | rndc | unbound-control |
| Python module support | No | Yes (pythonmod) |
| Systemd integration | N/A on FreeBSD | N/A on FreeBSD |
Common Deployment Patterns on FreeBSD
Pattern 1: Local Network Resolver (Unbound)
The most common use case. Unbound resolves DNS for your local network, validates DNSSEC, and caches results.
shsysrc local_unbound_enable="YES" # Edit /var/unbound/unbound.conf service local_unbound restart
Pattern 2: Authoritative + Recursive (Separated)
Best practice: run Unbound for recursion and NSD or BIND for authoritative zones on separate IPs or ports.
sh# Unbound on 127.0.0.1:53 for recursion # BIND on public IP:53 for authoritative zones pkg install unbound nsd # or bind918
Pattern 3: Combined Authoritative + Recursive (BIND)
BIND can do both in one process using views:
shellview "internal" { match-clients { 10.0.0.0/8; }; recursion yes; zone "example.com" { type master; file "example.com.zone"; }; }; view "external" { match-clients { any; }; recursion no; zone "example.com" { type master; file "example.com.external.zone"; }; };
This works but is not recommended for security or performance reasons. Separating the functions is better.
Pattern 4: DNS-over-TLS Forwarder (Unbound)
Unbound as a local resolver that forwards all queries over TLS to an upstream provider:
yamlserver: interface: 127.0.0.1 do-not-query-localhost: no forward-zone: name: "." forward-tls-upstream: yes forward-addr: 1.1.1.1@853#cloudflare-dns.com forward-addr: 1.0.0.1@853#cloudflare-dns.com
Monitoring and Troubleshooting
Unbound
sh# Statistics unbound-control stats_noreset # Dump cache unbound-control dump_cache # Lookup debug unbound-host -v -d example.com # Flush cache entry unbound-control flush example.com
BIND
sh# Statistics rndc stats cat /usr/local/etc/namedb/working/named.stats # Dump cache rndc dumpdb -cache # Debug query dig @127.0.0.1 example.com +trace # Flush cache rndc flush
FAQ
Should I use the base system Unbound or install from packages?
The base system local_unbound is sufficient for a local caching resolver. If you need advanced features (RPZ, DNS-over-HTTPS, Python modules, remote access), install the package version which is typically newer and compiled with more options.
Can I use Unbound as an authoritative server?
Not in any meaningful way. Unbound can serve local-data entries for local overrides, but it cannot load zone files, handle zone transfers, or perform DNSSEC signing. For authoritative DNS, use BIND, NSD, or knot.
Is BIND too insecure to use?
No. BIND 9.18+ is significantly more secure than older versions. ISC has invested heavily in security. However, if you only need recursive resolution, Unbound's smaller attack surface is objectively safer. Use BIND where you need its features (authoritative zones, dynamic updates, views). Use Unbound where recursive resolution is all you need.
How do they handle DNS amplification attacks?
Both support Response Rate Limiting (RRL) to mitigate DNS amplification. Unbound enables it by default for recursive mode. BIND requires explicit configuration. For authoritative servers facing amplification attacks, BIND's RRL is well-tested and effective.
What about PowerDNS as an alternative?
PowerDNS is a strong alternative, especially PowerDNS Recursor (for resolution) and PowerDNS Authoritative (for zones). It offers database-backed zone storage (MySQL, PostgreSQL), a REST API, and Lua scripting. On FreeBSD, it is available via pkg install powerdns powerdns-recursor. Consider PowerDNS if you need API-driven zone management or database-backed DNS.
How much memory should I allocate to the DNS cache?
For Unbound serving a network of 1,000 users: 128MB msg-cache-size and 256MB rrset-cache-size is generous. For 10,000+ users: 512MB and 1GB respectively. Unbound's cache is efficient -- even 64MB handles most small networks well. BIND's cache is less memory-efficient and benefits from more allocation.
Can Unbound and BIND coexist on the same FreeBSD host?
Yes. Run them on different IP addresses or different ports. A common pattern: Unbound on 127.0.0.1:53 for local recursion, BIND on the public IP:53 for authoritative zones. Configure BIND to forward recursive queries to Unbound, or disable recursion in BIND entirely.