DNS
DNS resolution and authoritative service for the home.arpa domain.
Design principles: See Lab Philosophy
Purpose
DNS serves two functions:
- Recursive resolution — All hosts use these servers to resolve external domains
- Authoritative service — Provides canonical name resolution for
home.arpa
The design prioritizes control, speed, and simplicity over feature richness.
Architecture
Two DNS servers provide redundancy:
- dns-auth01 (
10.10.110.53) — Primary DNS server - dns-auth02 (
10.10.110.54) — Secondary DNS server
Both servers run identical configurations and operate independently. Either can fail without disrupting name resolution.
Current deployment:
- Both VMs run on
thor(EPYC 7402P Proxmox host) - Future: One will migrate to a new host for true hardware redundancy
Implementation
Software: Unbound
Unbound is chosen for:
- Pure recursive resolution (no forwarding to upstream resolvers)
- Built-in DNSSEC validation
- Native support for authoritative local zones
- Single daemon with no database or web interface
- Predictable performance characteristics
Configuration Philosophy
The configuration emphasizes:
- No forwarding — Direct recursive resolution from root servers
- No logging — Pure speed, no query logging overhead
- No dashboard — Single daemon, managed via configuration files
- Full control — All resolution behavior is explicit and auditable
This is not a Pi-hole replacement with a web UI. It is a fast, transparent DNS resolver with ad blocking built in.
Authoritative Zone: home.arpa
The home.arpa zone is managed inline in the Unbound configuration.
Zone structure:
home.arpa. SOA, NS records
ns1.home.arpa. 10.10.110.53 (dns-auth01)
ns2.home.arpa. 10.10.110.54 (dns-auth02)
Host records:
All infrastructure hosts, VMs, and network equipment receive static A records. PTR records provide reverse DNS for all assigned addresses.
Example entries:
thor.home.arpa. 10.10.110.125
truenas.home.arpa. 10.10.110.219
ai.home.arpa. 10.10.110.221
netbox.home.arpa. 10.10.99.70
CNAMEs are used sparingly for service aliases:
proxmox.home.arpa. CNAME truenas.home.arpa.
unbound.home.arpa. CNAME dns-auth01.home.arpa.
Ad Blocking
DNS-based ad blocking is implemented via dynamically generated blocklists.
Blocklist sources:
- OISD Big — Comprehensive ad/tracker list
- StevenBlack hosts — Well-maintained unified hosts
Generation process:
A Python script (/opt/unbound-blocklist/generate.py) fetches upstream lists, merges them, applies an allowlist, and generates Unbound local-zone statements.
Blocked domains return NXDOMAIN rather than a redirect.
Allowlist:
Domains in /opt/unbound-blocklist/allowlist.txt are subtracted from the blocklist to prevent overblocking.
Update frequency:
Blocklists are regenerated daily via cron. Unbound reloads configuration automatically when changes are detected.
Performance Tuning
The configuration is tuned for a small network (~50 clients):
- Cache size: 128M message cache, 256M RRset cache
- Threads: 4 (matches VM vCPU count)
- Prefetching: Enabled for popular domains
- QNAME minimization: Reduces upstream query leakage
- Serve expired: Continues serving cached responses during upstream failures
These settings prioritize low latency over maximum throughput.
DNSSEC
DNSSEC validation is enabled and enforced.
- Root trust anchor is maintained automatically
- Permissive mode is disabled (invalid signatures are rejected)
- Algorithm downgrade attacks are prevented
Domains with broken DNSSEC will fail to resolve. This is intentional and considered correct behavior.
Access Control
DNS is restricted to RFC 1918 private address space:
10.0.0.0/8 allow
172.16.0.0/12 allow
192.168.0.0/16 allow
0.0.0.0/0 refuse
Public internet queries are rejected.
DHCP Integration
Current state: DNS and DHCP are not integrated.
DHCP is handled by the MikroTik edge router. DNS records are managed manually in the Unbound configuration.
Future plan:
DHCP will be automated from NetBox:
- NetBox defines intended IP assignments
- Automation generates both DHCP reservations and DNS records
- Configuration is pushed to infrastructure services
This is planned but not yet implemented.
Zone Management
Current workflow:
- Edit
/etc/unbound/unbound.conf.d/unbound.confdirectly - Update SOA serial (format:
YYYYMMDDNN) - Run
unbound-control reloadto apply changes - Verify with
dig @localhost <hostname>.home.arpa
No dynamic updates. All changes are made via configuration file edits.
This is deliberate: DNS changes are infrequent and require review.
Monitoring
Health checks:
- Query resolution latency (via LibreNMS or Prometheus)
- DNSSEC validation status
- Cache hit rate (via
unbound-control stats)
No query logging. Performance and privacy are prioritized over observability of individual queries.
Design Notes
- Recursive + authoritative in one daemon — Simpler than split-horizon BIND
- No zone transfers — Both servers use identical static configuration
- No conditional forwarding — All queries resolve recursively or from
home.arpa - Blocklist is additive — Upstream changes are merged, not blindly replaced
This design reflects a preference for operational clarity over DNS protocol purity.
Related Documentation
- Network Monitoring & Observability — DNS monitoring strategy
- NetBox as Source of Truth — Future DHCP/DNS automation
Configuration Reference
Primary config: /etc/unbound/unbound.conf.d/unbound.conf
Blocklist: /etc/unbound/unbound.conf.d/blocklist.conf (generated)
Blocklist generator: /opt/unbound-blocklist/generate.py
Sources: /opt/unbound-blocklist/sources.txt
Allowlist: /opt/unbound-blocklist/allowlist.txt
This document describes the current DNS infrastructure.
Future DNS systems are expected to follow the same design principles unless explicitly documented otherwise.