Synopsis #
unbound(8) is a validating, recursive, caching DNS resolver included in the OpenBSD base system. It is distinct from unwind(8) , which integrates local resolution with changing network proposals, and nsd(8) , which serves authoritative zones.
This chapter configures Unbound as a LAN resolver on 10.10.10.1. It leaves the router’s own /etc/resolv.conf under resolvd(8)
control. This separation allows the router to keep using its normal local resolver path while Unbound listens only on the LAN address.
Unbound is included in base but is not the automatically integrated default resolver. Enabling the daemon does not by itself make either the local host or LAN clients use it.
Choose the Resolver Role #
Use Unbound when a stable host should provide recursive service to an explicitly controlled network. Use unwind for an automatically integrated resolver on a workstation or mobile host. Use nsd for authoritative DNS data.
Do not expose recursive service to the Internet. An open resolver can be abused for reflection attacks and consumes resources on behalf of untrusted clients.
Create the Configuration #
The default configuration path is /var/unbound/etc/unbound.conf. Preserve any existing local policy and create a protected backup before replacing it.
For a resolver at 10.10.10.1 serving 10.10.10.0/24, use:
server:
interface: 10.10.10.1
access-control: 0.0.0.0/0 refuse
access-control: 10.10.10.0/24 allow
hide-identity: yes
hide-version: yes
harden-glue: yes
harden-dnssec-stripped: yes
auto-trust-anchor-file: "/var/unbound/db/root.key"
The explicit refuse rule makes the allowed client set reviewable. Add IPv6 interfaces and access-control entries only for prefixes that are actually routed and protected.
Initialize or update the DNSSEC root trust anchor with unbound-anchor(8) :
# unbound-anchor -a /var/unbound/db/root.key
The command can use built-in trust material when the network is unavailable. The Unbound account must be able to update the anchor and its directory when RFC 5011 tracking is enabled.
Validate the configuration with unbound-checkconf(8) :
# unbound-checkconf /var/unbound/etc/unbound.conf
Add Local Names #
Small static overrides can use local-zone and local-data in the server section:
local-zone: "internal.example." static
local-data: "router.internal.example. IN A 10.10.10.1"
local-data: "files.internal.example. IN A 10.10.10.20"
Use a trailing dot for complete DNS names. A static local zone answers only data configured for that zone and returns negative answers for other names below it. Larger or dynamically maintained authoritative zones belong on an authoritative server.
Add PF Rules #
Permit DNS from the controlled LAN to the resolver address over both UDP and TCP:
lan = "vlan10"
lan_net = "10.10.10.0/24"
pass in on $lan proto { udp, tcp } from $lan_net to 10.10.10.1 port domain
TCP is required for responses that do not fit in UDP, zone-related operations where allowed, and normal fallback behavior. Do not add a general Internet-facing port 53 rule.
Parse the complete policy before loading it:
# pfctl -nf /etc/pf.conf
# Check syntax without changing the active ruleset
# pfctl -f /etc/pf.conf
# Load the verified policy
Enable and Test Unbound #
Enable and start the daemon with rcctl(8) :
# rcctl enable unbound
# Start Unbound during boot
# rcctl start unbound
# Start recursive service now
# rcctl check unbound
# Confirm the daemon remains running
Confirm that only the intended address and port are listening:
$ netstat -na -f inet | grep '\.53 '
From a LAN client, query the resolver directly with host(1) :
$ host openbsd.org 10.10.10.1
# Test public recursive resolution
$ host router.internal.example 10.10.10.1
# Test the local override
Repeat a public query and inspect service logs when resolution is slow or fails. Use tcpdump(8) to separate client reachability from upstream recursion:
# tcpdump -ni vlan10 port 53
# Observe client queries and replies
# tcpdump -ni egress port 53
# Observe recursive queries to authoritative servers
Direct Clients to the Resolver #
Static clients can place nameserver 10.10.10.1 in their resolver configuration. DHCP service should advertise 10.10.10.1 as the domain-name server for the corresponding subnet.
Do not make /etc/resolv.conf immutable. On OpenBSD clients, resolvd merges proposals from DHCP, SLAAC, VPNs, and supported network devices. Resolver ownership must remain explicit when a client moves between networks.
Make the Router Use Unbound #
The LAN-only design does not change the router’s local resolver. If the router must also query Unbound, add a loopback interface to unbound.conf, permit loopback clients, and make one resolver owner select it.
One possible stable-server design is:
server:
interface: 127.0.0.1
interface: 10.10.10.1
access-control: 127.0.0.0/8 allow
access-control: 10.10.10.0/24 allow
The interaction among resolvd, unwind, DHCP or SLAAC proposals, fallback resolvers, and /etc/resolv.conf must be designed before changing local ownership. Disabling resolvd is not required for the LAN-only deployment and should not be presented as a generic Unbound prerequisite.
Optional Remote Control #
unbound-control(8) requires a configured control channel. Do not assume that it works merely because the resolver daemon is running.
When operational requirements justify it, configure a local Unix control socket or use unbound-control-setup according to the current manual. Keep the control endpoint local and restrict filesystem access. Then validate commands such as status, statistics, reload, and cache flush in a maintenance window.
Troubleshooting #
- A startup failure should be investigated with
unbound-checkconf, service logs, address ownership, and existing port 53 listeners. - Client timeouts with no packets on the LAN interface indicate client configuration, routing, VLAN, or PF problems.
- Client packets with no upstream queries indicate Unbound access control, configuration, or DNSSEC state.
- Upstream queries with no replies indicate routing, provider filtering, or upstream reachability.
SERVFAILcan be a correct DNSSEC-validation result. Check time synchronization and validation logs before weakening DNSSEC.- Local names that return
NXDOMAINshould be checked for trailing dots, zone type, and exact owner names.
See Configure Name Services for authoritative and recursive DNS roles and Build a Simple Router and Firewall for a LAN service example.