Run a private Unbound validating recursive resolver
Build a private, cache-enabled Unbound resolver that performs recursion itself, validates DNSSEC, minimizes query names, and refuses clients outside an explicit network.
Provide reliable DNS resolution for an administered network without forwarding the complete query stream to a public resolver, while preserving DNSSEC validation, bounded access, observable failure states, and a reversible client rollout.
- Ubuntu Server 24.04 LTS
- Unbound 1.19.x
- Dedicated address Reserve a stable private address for the resolver and confirm that no other service owns TCP or UDP port 53 on it.
ip -brief address; sudo ss -lntup '( sport = :53 )' - Client and management networks Write down the exact client CIDR that may recurse and a smaller management source range. Never infer these ranges from an interface name alone.
ip route show - Accurate time DNSSEC signatures and RFC 5011 trust-anchor maintenance depend on correct time. Resolve NTP problems before diagnosing validation.
timedatectl status - Rollback DNS Keep the currently working resolver addresses and a tested way to restore DHCP, VPN, or static client settings.
- Outbound DNS policy Confirm the host may reach authoritative servers over both UDP and TCP port 53. A UDP-only egress rule is incomplete.
OneLiners never runs these steps or stores secrets. Review placeholders, versions, current state, and change-control requirements before using a command.
Full guide
What you will build
- A private recursive DNS service on {{resolverAddress}} that starts with root hints, follows delegations, validates signed answers, caches results, and serves only {{clientCidr}}.
- An explicit trust path based on the root DNSSEC anchor maintained by unbound-anchor under the Unbound service account.
- A small home.arpa namespace for private hostnames that does not counterfeit or disable validation for a public signed domain.
- A staged client migration, deterministic rollback, and operational probes for UDP, TCP, DNSSEC, access-control, latency, time, and service health.
- You can distinguish recursion, forwarding, caching, DNSSEC validation, and local-zone synthesis instead of treating them as one black-box DNS action.
- You can prove that the resolver fails closed for a bogus DNSSEC chain and does not offer recursion to an untrusted source.
- You can diagnose whether a failure belongs to clients, firewall, transport, delegation, time, trust-anchor state, or upstream authoritative data.
- You retain a working client rollback path and avoid the common secondary-resolver configuration that silently bypasses the intended privacy boundary.
Architecture
How the parts fit together
Clients send DNS to one private address. Unbound iterates from the public root through TLD and child authoritative servers, sends only the minimum useful query name where possible, validates returned RRsets against the DNSSEC chain, and caches accepted data. It answers home.arpa locally and refuses recursion outside the allowlist.
- An allowed client sends a recursive query to {{resolverAddress}}. An unapproved source is refused before recursion becomes a resource-amplification service.
- On a cache miss, Unbound starts from root hints and follows referrals. Query-name minimisation avoids sending the full hostname to every earlier delegation point when protocol state permits.
- Unbound receives data and DNSSEC proofs, walks DS and DNSKEY relationships toward the configured root anchor, and returns SERVFAIL rather than an answer when a signed chain is bogus.
- Accepted data is cached only for its TTL and served more quickly to later clients. Negative answers can be cached and synthesized from authenticated denial where safe.
- Private home.arpa names terminate in local-zone data and never leak to the public hierarchy. Operational tests compare direct resolver behavior with client-visible behavior.
Assumptions
- The example uses Ubuntu Server 24.04 LTS and its Unbound 1.19.x package. Package revisions may change; the recorded build and validator module are acceptance evidence.
- {{resolverAddress}} is a stable private IPv4 address already configured on {{clientInterface}}. This guide deliberately leaves IPv6 listening disabled until an explicit IPv6 allowlist and firewall design exists.
- {{clientCidr}} is the complete and only network that may recurse. {{managementCidr}} is used for administration but does not automatically grant DNS access unless included in policy.
- The host can reach the public DNS hierarchy over UDP and TCP port 53 and can synchronize time. Transparent DNS interception or a corporate forced forwarder is outside the assumed design.
- Authoritative public zones are hosted elsewhere. Combining public authority and unrestricted recursion on one listener creates ambiguous policy and avoidable abuse risk.
- Client migration can be staged. If DHCP, VPN, or MDM settings cannot be rolled back, pause before changing them.
Key concepts
- Recursive resolver
- A service that accepts a client question, finds the answer by following DNS delegations, validates policy, caches the result, and returns the final response. It is different from an authoritative server that publishes data for zones it owns.
- Iterative query
- A query made by the resolver to an authoritative server while following referrals. Unbound performs the sequence; ordinary clients continue to request recursion from Unbound.
- DNSSEC validation
- Cryptographic verification that signed DNS data matches an authenticated chain from a configured trust anchor. It authenticates DNS data, not the confidentiality of the query or the honesty of an unsigned zone.
- Trust anchor
- A configured DNSKEY or digest that starts validation. For the public DNS, the root key anchors the chain. Losing write access, correct time, or maintenance state can convert valid names into local SERVFAIL.
- AD flag
- The Authenticated Data response flag, which a validating resolver sets when the answer and relevant chain were validated. It must be interpreted together with where the query was sent and whether checking was disabled.
- QNAME minimisation
- A privacy technique that sends only the name portion needed at each delegation step where practical, reducing unnecessary disclosure of a complete hostname to root and TLD servers.
- Negative caching
- Caching an authenticated non-existence result for its permitted lifetime. It improves performance but means a newly created name may remain unseen until the prior negative TTL expires.
- Open resolver
- A recursive resolver reachable by arbitrary internet sources. It can be abused for reflection, resource consumption, and laundering query traffic; access-control and firewall policy both must prevent it.
- Split namespace
- A name whose internal and public answers differ. It requires explicit ownership and DNSSEC design. The reserved home.arpa zone is safer for purely local names than copying an unsigned version of a signed public zone.
Before you copy
Values used in this guide
{{resolverAddress}}Stable private IPv4 address used by clients to reach Unbound.
Example: 10.24.0.53{{clientCidr}}Exact IPv4 range allowed to request recursion.
Example: 10.24.0.0/24{{managementCidr}}Smaller administrator source range used for SSH and management policy.
Example: 10.24.0.0/28{{clientInterface}}Interface that owns resolverAddress and receives client DNS.
Example: ens18{{routerAddress}}Private router address exposed as router.home.arpa.
Example: 10.24.0.1Security and production boundaries
- DNSSEC does not encrypt queries. Clients on the local network, the resolver host, and authoritative destinations can still observe portions of traffic. Add an explicitly designed encrypted client transport only after preserving validation, policy, and observability.
- The resolver must not listen on or allow an untrusted public address. An Unbound access-control refusal is necessary, but a firewall boundary provides independent protection and limits accidental future configuration drift.
- Do not add domain-insecure for a failing public signed zone as a routine workaround. That turns a useful integrity alarm into silent acceptance. Investigate time, transport, trust anchor, delegation, and authoritative signatures first.
- TCP port 53 is required. DNSSEC responses and ordinary large answers can be truncated over UDP, causing a standards-compliant retry over TCP. Blocking it creates intermittent failures that appear domain-specific.
- The trust anchor file is writable operational state, not a secret. Protect its ownership and integrity, back it up with configuration, and never replace it blindly from an untrusted host.
- Query logs may contain internal names, user activity, incident indicators, and personal data. Set retention and access controls deliberately instead of enabling maximum verbosity indefinitely.
Stop before continuing if
- Stop if the host has no tested working DNS fallback for package installation and client rollback.
- Stop if TCP port 53 outbound is blocked or transparently redirected and the network owner cannot provide a documented supported path.
- Stop if system time is wrong, unsynchronized, or jumps after boot. DNSSEC evidence is not trustworthy until time is corrected.
- Stop if port 53 is already owned by a required service and you cannot allocate a separate address or safely change the topology.
- Stop if {{clientCidr}} includes an internet-facing or guest network that should not have recursion.
- Stop rollout on the first DNSSEC-valid domain that returns unexplained SERVFAIL, or on any unapproved source that receives a recursive answer.
decision
Define the resolver boundary before installing it
Choose one stable resolver address, one allowed client CIDR, and a staged rollout group. Keep authoritative service and recursive service on separate addresses or hosts so that public authority never becomes an open resolver.
Why this step matters
Resolver exposure is an architectural decision, not a final firewall tweak. Recording the address and client boundary first prevents an accidental public listener and makes every later query test attributable to the correct network path.
What to understand
A recursive resolver consumes work on behalf of clients and can produce responses larger than requests. Restricting recursion protects both the operator and unrelated internet targets.
Authoritative and recursive DNS have opposite exposure needs: public authority must answer everyone but should not recurse; private recursion should answer approved clients but has no public zone authority.
The empty socket output in the example is a deliberate precondition. If another process appears, identify its package, configuration owner, and clients before changing it.
Keep the command output with the change record. DNS is distributed and cached, so an immediate local success is only one layer of evidence; later checkpoints deliberately test authoritative behavior, delegation, validation, transport, and client-visible results separately.
Run the exact read-only checkpoint before moving on. If its evidence differs from the example, diagnose that layer instead of stacking another configuration change, restarting repeatedly, or weakening a security control to make a query appear successful.
System changes
- No service state changes; this step creates the approved addressing, access, management, transport, and rollback record.
Syntax explained
ip route get ADDRESS- Shows the kernel-selected local route and source for the planned address.
sport = :53- Limits socket inspection to processes already listening on DNS port 53.
Values stay on this page and are never sent or saved.
printf 'resolver=%s\nclients=%s\nmanagement=%s\n' '{{resolverAddress}}' '{{clientCidr}}' '{{managementCidr}}'; ip route get {{resolverAddress}}; sudo ss -lntup '( sport = :53 )'resolver=10.24.0.53 clients=10.24.0.0/24 management=10.24.0.0/28 local 10.24.0.53 dev lo src 10.24.0.53 uid 0 Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
Checkpoint: Freeze the intended DNS boundary
Continue whenThe address is stable and local, the CIDRs are approved, no conflicting listener exists, and current client DNS is recorded.
Stop whenThe address is dynamic, port 53 is occupied, an untrusted range is included, or rollback ownership is unknown.
If this step fails
The “Freeze the intended DNS boundary” checkpoint does not produce the expected evidence.
Likely causeThe preceding change is incomplete, the observed system differs from the documented assumptions, or the checkpoint reached a different DNS component than intended. Expected evidence: The address is stable and local, the CIDRs are approved, no conflicting listener exists, and current client DNS is recorded.
Compare the observed state with the documented checkpoint evidence before making another change.Review the immediately preceding command or configuration diff, service status, listener ownership, journal timestamps, and the exact server address queried.
ResolutionStop at this layer and correct the discrepancy before continuing. The address is dynamic, port 53 is occupied, an untrusted range is included, or rollback ownership is unknown.
Security notes
- Do not widen the allowlist for convenience during setup; test from a host that actually belongs to the intended client network.
- Do not paste private names, client addresses, keys, complete query logs, or registrar account details into public support channels. Redact evidence while retaining timestamps, response codes, flags, serials, key tags, and server identities needed for diagnosis.
Alternatives
- Allocate a separate address, VLAN, or host when an existing DNS filter or authoritative service already owns port 53.
Stop conditions
- Do not install into an ambiguous topology and hope the later firewall will clarify it.
command
Install Unbound and DNS diagnostic tools
Install the distribution packages, record the exact Unbound build, and verify that the binary includes DNSSEC support before creating service configuration.
Why this step matters
Distribution packages provide a maintained unit, service user, filesystem layout, and linked security libraries. Recording the build and validator module turns an assumption about capability into evidence.
What to understand
The validator and iterator modules in unbound -V are required for the design. A minimal or vendor-modified build may behave differently.
dnsutils supplies dig for protocol-level testing. It is not part of the resolver data path and may be removed later under local package policy.
Review apt's proposed transaction before approval on a production host and record whether dependencies schedule a reboot.
Keep the command output with the change record. DNS is distributed and cached, so an immediate local success is only one layer of evidence; later checkpoints deliberately test authoritative behavior, delegation, validation, transport, and client-visible results separately.
Run the exact read-only checkpoint before moving on. If its evidence differs from the example, diagnose that layer instead of stacking another configuration change, restarting repeatedly, or weakening a security control to make a query appear successful.
System changes
- Installs Unbound, unbound-anchor, dig, service metadata, and package-managed defaults; apt may update dependency metadata.
Syntax explained
--yes- Accepts the displayed package transaction; use only after reviewing the plan.
unbound -V- Prints exact build, linked libraries, modules, and compile configuration.
sudo apt update && sudo apt install --yes unbound unbound-anchor dnsutils && unbound -V | sed -n '1,8p'Version 1.19.2 linked libs: libevent 2.1.12-stable (it uses epoll), OpenSSL 3.0.13 linked modules: dns64 respip validator iterator configured for x86_64-pc-linux-gnu
Checkpoint: Accept the packaged resolver capability
Continue whenUnbound reports version 1.19.x with validator and iterator modules and apt has no unresolved errors.
Stop whenThe build lacks validation, package origin is unexpected, or installation changes a required existing resolver.
If this step fails
The “Accept the packaged resolver capability” checkpoint does not produce the expected evidence.
Likely causeThe preceding change is incomplete, the observed system differs from the documented assumptions, or the checkpoint reached a different DNS component than intended. Expected evidence: Unbound reports version 1.19.x with validator and iterator modules and apt has no unresolved errors.
Compare the observed state with the documented checkpoint evidence before making another change.Review the immediately preceding command or configuration diff, service status, listener ownership, journal timestamps, and the exact server address queried.
ResolutionStop at this layer and correct the discrepancy before continuing. The build lacks validation, package origin is unexpected, or installation changes a required existing resolver.
Security notes
- Use signed distribution repositories and do not pipe third-party installation scripts into a privileged shell.
- Do not paste private names, client addresses, keys, complete query logs, or registrar account details into public support channels. Redact evidence while retaining timestamps, response codes, flags, serials, key tags, and server identities needed for diagnosis.
Alternatives
- Use the vendor-supported package for another distribution and translate filesystem paths and confinement rules explicitly.
Stop conditions
- Do not continue with an unknown custom binary simply because the executable name is unbound.
command
Initialize and inspect the DNSSEC root trust anchor
Create or refresh the writable root trust-anchor file as the Unbound service user, then check ownership, time, and the managed-key material before enabling validation.
Why this step matters
A validator needs a locally trusted starting point. unbound-anchor verifies and maintains a writable root-key state, while correct ownership allows the confined service to update RFC 5011 metadata over time.
What to understand
The root anchor is public key material, not a password, but unauthorized replacement can make forged chains appear trusted or valid chains fail.
Run maintenance as the service identity so that a root-owned test does not hide permission failure that appears only after service start.
The printed DNSKEY line proves content exists; subsequent positive and deliberately broken validation tests prove that Unbound actually uses it.
Keep the command output with the change record. DNS is distributed and cached, so an immediate local success is only one layer of evidence; later checkpoints deliberately test authoritative behavior, delegation, validation, transport, and client-visible results separately.
Run the exact read-only checkpoint before moving on. If its evidence differs from the example, diagnose that layer instead of stacking another configuration change, restarting repeatedly, or weakening a security control to make a query appear successful.
System changes
- Creates or refreshes /var/lib/unbound/root.key and its RFC 5011 managed state under the unbound account.
Syntax explained
-a /var/lib/unbound/root.key- Selects the auto-trust-anchor file used later by the server configuration.
sudo -u unbound- Exercises the same filesystem permissions as the running resolver.
sudo install -d -o unbound -g unbound -m 0755 /var/lib/unbound && sudo -u unbound unbound-anchor -a /var/lib/unbound/root.key && sudo stat -c '%U:%G %a %n' /var/lib/unbound/root.key && grep -E 'DNSKEY|managed-keys' /var/lib/unbound/root.key | headunbound:unbound 644 /var/lib/unbound/root.key . 172800 IN DNSKEY 257 3 8 AwEAAaz/tAm8yTn4Mfeh5eyI...
Checkpoint: Establish a usable root anchor
timedatectl status; sudo -u unbound unbound-anchor -a /var/lib/unbound/root.keyContinue whenTime is synchronized, the command succeeds, and root.key is readable and maintainable by unbound.
Stop whenTime is wrong, the file is empty, ownership differs, or anchor maintenance reports failure.
If this step fails
The “Establish a usable root anchor” checkpoint does not produce the expected evidence.
Likely causeThe preceding change is incomplete, the observed system differs from the documented assumptions, or the checkpoint reached a different DNS component than intended. Expected evidence: Time is synchronized, the command succeeds, and root.key is readable and maintainable by unbound.
Run the read-only checkpoint again and preserve its complete output: timedatectl status; sudo -u unbound unbound-anchor -a /var/lib/unbound/root.keyReview the immediately preceding command or configuration diff, service status, listener ownership, journal timestamps, and the exact server address queried.
ResolutionStop at this layer and correct the discrepancy before continuing. Time is wrong, the file is empty, ownership differs, or anchor maintenance reports failure.
Security notes
- Investigate unexpected key changes and protect directory integrity; never download an anchor from an arbitrary mirror to clear SERVFAIL.
- Do not paste private names, client addresses, keys, complete query logs, or registrar account details into public support channels. Redact evidence while retaining timestamps, response codes, flags, serials, key tags, and server identities needed for diagnosis.
Alternatives
- Provision a reviewed anchor through configuration management while preserving RFC 5011 state, ownership, and rollover monitoring.
Stop conditions
- Do not disable validation to compensate for a broken anchor or clock.
config
Write an explicitly private validating resolver configuration
Bind only the planned addresses, refuse every client by default, permit the exact private CIDR, enable the validator, and retain TCP support for large or truncated DNSSEC responses.
Why this step matters
Secure defaults become auditable only when important listener, client, transport, validation, privacy, and disclosure settings are explicit. The configuration makes refusal the default and adds one narrow exception.
What to understand
do-tcp remains enabled because a truncated UDP response must retry over TCP; DNSSEC increases the frequency of large responses.
harden-dnssec-stripped rejects cases where expected signatures appear removed, while qname minimisation reduces unnecessary label disclosure during iteration.
do-ip6 is disabled for this IPv4-only example. Enabling it later requires an IPv6 listener, allowlist, firewall, route, and two-transport acceptance tests.
Keep the command output with the change record. DNS is distributed and cached, so an immediate local success is only one layer of evidence; later checkpoints deliberately test authoritative behavior, delegation, validation, transport, and client-visible results separately.
Run the exact read-only checkpoint before moving on. If its evidence differs from the example, diagnose that layer instead of stacking another configuration change, restarting repeatedly, or weakening a security control to make a query appear successful.
System changes
- Creates /etc/unbound/unbound.conf.d/oneliners.conf and changes listener, recursion, validation, privacy, and cache behavior after reload.
Syntax explained
access-control: 0.0.0.0/0 refuse- Makes refusal the IPv4 default before the specific allow rule is evaluated.
auto-trust-anchor-file- Enables validation from managed root-key state rather than a hard-coded temporary key.
qname-minimisation: yes- Reduces the full query name exposed to earlier delegation points.
/etc/unbound/unbound.conf.d/oneliners.confValues stay on this page and are never sent or saved.
server:
interface: 127.0.0.1
interface: {{resolverAddress}}
port: 53
access-control: 0.0.0.0/0 refuse
access-control: {{clientCidr}} allow
do-udp: yes
do-tcp: yes
do-ip6: no
auto-trust-anchor-file: "/var/lib/unbound/root.key"
qname-minimisation: yes
harden-dnssec-stripped: yes
harden-glue: yes
harden-below-nxdomain: yes
aggressive-nsec: yes
prefetch: yes
prefetch-key: yes
hide-identity: yes
hide-version: yes
unwanted-reply-threshold: 100000
val-clean-additional: yes
verbosity: 1server: interface: 127.0.0.1 interface: 10.24.0.53 port: 53 access-control: 0.0.0.0/0 refuse access-control: 10.24.0.0/24 allow auto-trust-anchor-file: "/var/lib/unbound/root.key" qname-minimisation: yes harden-dnssec-stripped: yes prefetch: yes
Checkpoint: Review explicit resolver policy
Continue whenOnly loopback and {{resolverAddress}} listen; only {{clientCidr}} is allowed; validator, UDP, and TCP are enabled.
Stop whenA wildcard public listener, broad allow rule, disabled validator, or UDP-only design appears.
If this step fails
The “Review explicit resolver policy” checkpoint does not produce the expected evidence.
Likely causeThe preceding change is incomplete, the observed system differs from the documented assumptions, or the checkpoint reached a different DNS component than intended. Expected evidence: Only loopback and {{resolverAddress}} listen; only {{clientCidr}} is allowed; validator, UDP, and TCP are enabled.
Compare the observed state with the documented checkpoint evidence before making another change.Review the immediately preceding command or configuration diff, service status, listener ownership, journal timestamps, and the exact server address queried.
ResolutionStop at this layer and correct the discrepancy before continuing. A wildcard public listener, broad allow rule, disabled validator, or UDP-only design appears.
Security notes
- Treat changing access-control to allow as an exposure change requiring independent network testing, not a harmless syntax fix.
- Do not paste private names, client addresses, keys, complete query logs, or registrar account details into public support channels. Redact evidence while retaining timestamps, response codes, flags, serials, key tags, and server identities needed for diagnosis.
Alternatives
- Bind to a dedicated VRF or private VLAN address for stronger routing isolation in addition to application policy.
Stop conditions
- Do not start the service until the rendered variables contain real addresses and no braces remain.
config
Add private names without weakening a public DNSSEC chain
Use the reserved home.arpa namespace for local-only records. Do not create an unsigned copy of a public signed zone and do not add domain-insecure merely to silence validation failures.
Why this step matters
The reserved home.arpa namespace gives a clear local authority boundary. It avoids shadowing a public signed zone, which otherwise creates confusing validation exceptions and different answers based on resolver location.
What to understand
static local-zone answers listed data and returns authoritative negative responses for other names under home.arpa.
private-address protects against public answers that point into RFC 1918 space unless an explicit policy says otherwise; review interactions with legitimate split services.
Short TTLs ease local changes, but clients and application caches may still retain negative or positive data until expiry.
Keep the command output with the change record. DNS is distributed and cached, so an immediate local success is only one layer of evidence; later checkpoints deliberately test authoritative behavior, delegation, validation, transport, and client-visible results separately.
Run the exact read-only checkpoint before moving on. If its evidence differs from the example, diagnose that layer instead of stacking another configuration change, restarting repeatedly, or weakening a security control to make a query appear successful.
System changes
- Creates local-zone.conf with two private records and private-address protections; these names become visible to approved resolver clients.
Syntax explained
local-zone: home.arpa. static- Makes Unbound authoritative for the local reserved zone and synthesizes negative answers for missing names.
local-data- Defines exact local resource records with explicit TTL, class, type, and value.
/etc/unbound/unbound.conf.d/local-zone.confValues stay on this page and are never sent or saved.
server:
local-zone: "home.arpa." static
local-data: "router.home.arpa. 300 IN A {{routerAddress}}"
local-data: "resolver.home.arpa. 300 IN A {{resolverAddress}}"
private-address: 10.0.0.0/8
private-address: 172.16.0.0/12
private-address: 192.168.0.0/16server: local-zone: "home.arpa." static local-data: "router.home.arpa. 300 IN A 10.24.0.1" local-data: "resolver.home.arpa. 300 IN A 10.24.0.53" private-address: 10.0.0.0/8
Checkpoint: Keep private data in a private namespace
Continue whenAll local names end in home.arpa, addresses are correct, and no domain-insecure exception exists.
Stop whenThe proposal duplicates a public zone, includes secrets, or conflicts with existing service discovery.
If this step fails
The “Keep private data in a private namespace” checkpoint does not produce the expected evidence.
Likely causeThe preceding change is incomplete, the observed system differs from the documented assumptions, or the checkpoint reached a different DNS component than intended. Expected evidence: All local names end in home.arpa, addresses are correct, and no domain-insecure exception exists.
Compare the observed state with the documented checkpoint evidence before making another change.Review the immediately preceding command or configuration diff, service status, listener ownership, journal timestamps, and the exact server address queried.
ResolutionStop at this layer and correct the discrepancy before continuing. The proposal duplicates a public zone, includes secrets, or conflicts with existing service discovery.
Security notes
- Private DNS names reveal topology to every approved client; authorization to recurse should match authorization to view this namespace.
- Do not paste private names, client addresses, keys, complete query logs, or registrar account details into public support channels. Redact evidence while retaining timestamps, response codes, flags, serials, key tags, and server identities needed for diagnosis.
Alternatives
- Delegate a dedicated internal subdomain from managed authority with a documented DNSSEC design when home.arpa is insufficient.
Stop conditions
- Do not solve a broken public DNSSEC chain by declaring the public domain insecure locally.
verification
Validate every included configuration file
Run Unbound's parser before touching the service and inspect the effective interface, access-control, trust-anchor, recursion, and TCP settings.
Why this step matters
Static parsing catches unknown directives, indentation mistakes, invalid networks, duplicate port ownership assumptions, and unreadable files before a reload can remove working DNS.
What to understand
Querying individual options makes the security-relevant effective values visible even when configuration is split across includes.
A successful parser does not prove routing or DNSSEC correctness, so it is a gate rather than the final acceptance test.
Save the rendered configuration output with the change record so later drift can be compared against intent.
Keep the command output with the change record. DNS is distributed and cached, so an immediate local success is only one layer of evidence; later checkpoints deliberately test authoritative behavior, delegation, validation, transport, and client-visible results separately.
Run the exact read-only checkpoint before moving on. If its evidence differs from the example, diagnose that layer instead of stacking another configuration change, restarting repeatedly, or weakening a security control to make a query appear successful.
System changes
- No persistent change; reads configuration and included files using Unbound's parser.
Syntax explained
-o OPTION- Prints the effective configured value for a selected directive.
unbound-checkconf- Performs an offline semantic and syntax check without starting the daemon.
sudo unbound-checkconf && sudo unbound-checkconf -o interface && sudo unbound-checkconf -o access-control && sudo unbound-checkconf -o auto-trust-anchor-fileunbound-checkconf: no errors in /etc/unbound/unbound.conf 127.0.0.1 10.24.0.53 0.0.0.0/0 refuse 10.24.0.0/24 allow /var/lib/unbound/root.key
Checkpoint: Require a clean static configuration
Continue whenNo errors appear and every printed address, CIDR, and anchor path matches the approved plan.
Stop whenAny warning or unexpected effective value remains, even if systemd could still start.
If this step fails
The “Require a clean static configuration” checkpoint does not produce the expected evidence.
Likely causeThe preceding change is incomplete, the observed system differs from the documented assumptions, or the checkpoint reached a different DNS component than intended. Expected evidence: No errors appear and every printed address, CIDR, and anchor path matches the approved plan.
Compare the observed state with the documented checkpoint evidence before making another change.Review the immediately preceding command or configuration diff, service status, listener ownership, journal timestamps, and the exact server address queried.
ResolutionStop at this layer and correct the discrepancy before continuing. Any warning or unexpected effective value remains, even if systemd could still start.
Security notes
- Never suppress an unknown directive without confirming whether the intended hardening feature is unsupported.
- Do not paste private names, client addresses, keys, complete query logs, or registrar account details into public support channels. Redact evidence while retaining timestamps, response codes, flags, serials, key tags, and server identities needed for diagnosis.
Alternatives
- Validate the same files in a matching disposable image as an additional pre-deployment check.
Stop conditions
- Do not restart or reload after a parser failure.
command
Permit the complete DNS transport path and restrict clients
Allow UDP and TCP port 53 to the resolver only from the approved client CIDR. Confirm that outbound policy permits UDP and TCP DNS to authoritative servers and that NTP remains available.
Why this step matters
Application refusal and packet filtering are independent defenses. The firewall limits exposure when configuration drifts, while complete UDP and TCP paths prevent domain-specific failures during recursion.
What to understand
Rules specify source, destination address, interface, protocol, and port so another service or interface does not inherit DNS exposure.
Outbound recursion contacts many authoritative addresses; destination allowlisting is generally impractical, but egress can still be limited to DNS protocols and monitored.
UFW numbering changes after edits. Record rule text and current numbers rather than storing a deletion number as permanent documentation.
Keep the command output with the change record. DNS is distributed and cached, so an immediate local success is only one layer of evidence; later checkpoints deliberately test authoritative behavior, delegation, validation, transport, and client-visible results separately.
Run the exact read-only checkpoint before moving on. If its evidence differs from the example, diagnose that layer instead of stacking another configuration change, restarting repeatedly, or weakening a security control to make a query appear successful.
System changes
- Adds inbound UDP and TCP allow rules for DNS from {{clientCidr}} to {{resolverAddress}} on {{clientInterface}}.
Syntax explained
from {{clientCidr}}- Restricts eligible packet sources before Unbound evaluates recursion policy.
to {{resolverAddress}} port 53- Avoids exposing another local address or DNS listener.
Values stay on this page and are never sent or saved.
sudo ufw allow in on {{clientInterface}} proto udp from {{clientCidr}} to {{resolverAddress}} port 53 comment 'private Unbound UDP' && sudo ufw allow in on {{clientInterface}} proto tcp from {{clientCidr}} to {{resolverAddress}} port 53 comment 'private Unbound TCP' && sudo ufw status numbered[ 1] 10.24.0.53 53/udp on ens18 ALLOW IN 10.24.0.0/24 # private Unbound UDP [ 2] 10.24.0.53 53/tcp on ens18 ALLOW IN 10.24.0.0/24 # private Unbound TCP
Checkpoint: Accept both required transports and no wider source
Continue whenExactly two matching inbound rules exist and outbound UDP/TCP DNS plus NTP are permitted.
Stop whenA rule uses Anywhere, targets the wrong interface/address, or TCP egress is prohibited.
If this step fails
The “Accept both required transports and no wider source” checkpoint does not produce the expected evidence.
Likely causeThe preceding change is incomplete, the observed system differs from the documented assumptions, or the checkpoint reached a different DNS component than intended. Expected evidence: Exactly two matching inbound rules exist and outbound UDP/TCP DNS plus NTP are permitted.
Compare the observed state with the documented checkpoint evidence before making another change.Review the immediately preceding command or configuration diff, service status, listener ownership, journal timestamps, and the exact server address queried.
ResolutionStop at this layer and correct the discrepancy before continuing. A rule uses Anywhere, targets the wrong interface/address, or TCP egress is prohibited.
Security notes
- Have console access before changing a remote firewall and preserve unrelated rules; this guide does not replace the complete policy.
- Do not paste private names, client addresses, keys, complete query logs, or registrar account details into public support channels. Redact evidence while retaining timestamps, response codes, flags, serials, key tags, and server identities needed for diagnosis.
Alternatives
- Implement equivalent nftables rules in the existing atomic ruleset and validate with nft -c before loading.
Stop conditions
- Do not flush or replace a production firewall to install two resolver rules.
command
Start the resolver and prove its listeners
Enable Unbound, inspect the journal and socket ownership, then query loopback before any client is switched. A running unit without a listener is not a successful checkpoint.
Why this step matters
A service is usable only when the unit, process, listeners, log, and local query agree. Testing loopback first isolates Unbound from client routing and firewall variables.
What to understand
systemctl active status proves process supervision, while ss proves the requested sockets actually belong to Unbound.
The local home.arpa answer tests include loading and local-zone synthesis without depending on internet authority.
Read the complete journal on failure; repeated blind restarts can overwrite the most useful first error and trigger rate limiting.
Keep the command output with the change record. DNS is distributed and cached, so an immediate local success is only one layer of evidence; later checkpoints deliberately test authoritative behavior, delegation, validation, transport, and client-visible results separately.
Run the exact read-only checkpoint before moving on. If its evidence differs from the example, diagnose that layer instead of stacking another configuration change, restarting repeatedly, or weakening a security control to make a query appear successful.
System changes
- Enables Unbound at boot, starts it now, opens configured listeners, and begins maintaining caches and the trust-anchor state.
Syntax explained
enable --now- Creates boot activation links and starts the unit in the same reviewed action.
+noall +answer- Displays the answer section only for a concise local data checkpoint.
sudo systemctl enable --now unbound && systemctl --no-pager --full status unbound && sudo ss -lntup '( sport = :53 )' && dig @127.0.0.1 resolver.home.arpa A +noall +answer● unbound.service - Unbound DNS server
Active: active (running)
udp UNCONN 0 0 10.24.0.53:53 0.0.0.0:* users:(("unbound",pid=1842,fd=6))
tcp LISTEN 0 256 10.24.0.53:53 0.0.0.0:* users:(("unbound",pid=1842,fd=7))
resolver.home.arpa. 300 IN A 10.24.0.53Checkpoint: Prove the local resolver process
Continue whenThe unit is active, Unbound owns loopback and {{resolverAddress}} on UDP/TCP 53, and resolver.home.arpa answers correctly.
Stop whenThe unit loops, another process owns a socket, a planned listener is absent, or local data is wrong.
If this step fails
The “Prove the local resolver process” checkpoint does not produce the expected evidence.
Likely causeThe preceding change is incomplete, the observed system differs from the documented assumptions, or the checkpoint reached a different DNS component than intended. Expected evidence: The unit is active, Unbound owns loopback and {{resolverAddress}} on UDP/TCP 53, and resolver.home.arpa answers correctly.
Compare the observed state with the documented checkpoint evidence before making another change.Review the immediately preceding command or configuration diff, service status, listener ownership, journal timestamps, and the exact server address queried.
ResolutionStop at this layer and correct the discrepancy before continuing. The unit loops, another process owns a socket, a planned listener is absent, or local data is wrong.
Security notes
- Confirm the listener list immediately; a mistaken wildcard bind is an incident even if the firewall currently masks it.
- Do not paste private names, client addresses, keys, complete query logs, or registrar account details into public support channels. Redact evidence while retaining timestamps, response codes, flags, serials, key tags, and server identities needed for diagnosis.
Alternatives
- Start without enabling during a maintenance window, then enable only after all acceptance checks pass.
Stop conditions
- Do not move clients while any local process or listener checkpoint fails.
verification
Prove positive and negative DNSSEC validation
Query a signed root key and a signed public name with the checking-disabled bit cleared, then query a deliberately broken DNSSEC test name. Require validated answers to carry AD and the broken chain to fail closed.
Why this step matters
Validation needs paired evidence: a correctly signed chain must succeed with AD, and a deliberately bogus chain must fail. Testing only successful names cannot distinguish validation from ordinary recursion.
What to understand
The checking-disabled bit is not set in these commands, allowing the resolver to enforce validation normally.
SERVFAIL for dnssec-failed.org is expected in this controlled negative test; SERVFAIL for all signed domains indicates a local fault.
AD is meaningful because the query is sent directly to the owned validating resolver. An arbitrary intermediary could set or clear it under different trust assumptions.
Keep the command output with the change record. DNS is distributed and cached, so an immediate local success is only one layer of evidence; later checkpoints deliberately test authoritative behavior, delegation, validation, transport, and client-visible results separately.
Run the exact read-only checkpoint before moving on. If its evidence differs from the example, diagnose that layer instead of stacking another configuration change, restarting repeatedly, or weakening a security control to make a query appear successful.
System changes
- No persistent change; creates cache entries for root, public positive, and intentionally broken validation paths.
Syntax explained
+dnssec- Requests DNSSEC records in responses and enables inspection of validation-related data.
+comments- Retains header status and flags, including AD and SERVFAIL evidence.
Values stay on this page and are never sent or saved.
dig @{{resolverAddress}} . DNSKEY +dnssec +noall +comments +answer; dig @{{resolverAddress}} cloudflare.com A +dnssec +noall +comments +answer; dig @{{resolverAddress}} dnssec-failed.org A +dnssec +noall +comments;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49012 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3 cloudflare.com. 300 IN A 104.16.132.229 ;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 21144 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0
Checkpoint: Require fail-closed validation
Continue whenRoot and signed public data return NOERROR with AD; the deliberately broken chain returns SERVFAIL and no answer.
Stop whenValid data lacks AD unexpectedly, broken data resolves, or every signed name fails.
If this step fails
The “Require fail-closed validation” checkpoint does not produce the expected evidence.
Likely causeThe preceding change is incomplete, the observed system differs from the documented assumptions, or the checkpoint reached a different DNS component than intended. Expected evidence: Root and signed public data return NOERROR with AD; the deliberately broken chain returns SERVFAIL and no answer.
Compare the observed state with the documented checkpoint evidence before making another change.Review the immediately preceding command or configuration diff, service status, listener ownership, journal timestamps, and the exact server address queried.
ResolutionStop at this layer and correct the discrepancy before continuing. Valid data lacks AD unexpectedly, broken data resolves, or every signed name fails.
Security notes
- Never create a local exception for the negative test domain; its failure is the proof that bogus data is rejected.
- Do not paste private names, client addresses, keys, complete query logs, or registrar account details into public support channels. Redact evidence while retaining timestamps, response codes, flags, serials, key tags, and server identities needed for diagnosis.
Alternatives
- Maintain owned signed and deliberately mis-signed fixture zones for deterministic internal validation probes.
Stop conditions
- Do not advertise the resolver to clients until both positive and negative evidence pass.
verification
Measure recursion and cache behavior without confusing it with correctness
Run the same uncached-style query twice and compare query time while checking the answer and AD state. Cache speed is useful only after validation and content are correct.
Why this step matters
Caching provides latency and authority-load benefits, but a fast wrong answer is still a failure. Comparing identical validated responses before timing avoids optimizing around stale or insecure data.
What to understand
The first query may already be cached because earlier checks touched related delegations, so absolute numbers are illustrative rather than a performance guarantee.
TTL controls remaining cache life; repeatedly querying does not reset the authoritative TTL.
Prefetch refreshes popular data near expiry but does not permit serving beyond protocol and configuration rules.
Keep the command output with the change record. DNS is distributed and cached, so an immediate local success is only one layer of evidence; later checkpoints deliberately test authoritative behavior, delegation, validation, transport, and client-visible results separately.
Run the exact read-only checkpoint before moving on. If its evidence differs from the example, diagnose that layer instead of stacking another configuration change, restarting repeatedly, or weakening a security control to make a query appear successful.
System changes
- No durable configuration change; populates and reads normal resolver cache entries.
Syntax explained
Query time- Measures the client-observed request latency reported by dig.
status and flags- Keeps correctness and validation state beside the timing comparison.
Values stay on this page and are never sent or saved.
dig @{{resolverAddress}} www.iana.org A +dnssec | grep -E 'status:|flags:|Query time'; dig @{{resolverAddress}} www.iana.org A +dnssec | grep -E 'status:|flags:|Query time';; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 17019 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1 ;; Query time: 86 msec ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60410 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1 ;; Query time: 0 msec
Checkpoint: Observe correct cached recursion
Continue whenBoth responses match, keep NOERROR and AD, and a later cached query is normally faster.
Stop whenAnswer, validation state, or TTL progression is inconsistent.
If this step fails
The “Observe correct cached recursion” checkpoint does not produce the expected evidence.
Likely causeThe preceding change is incomplete, the observed system differs from the documented assumptions, or the checkpoint reached a different DNS component than intended. Expected evidence: Both responses match, keep NOERROR and AD, and a later cached query is normally faster.
Compare the observed state with the documented checkpoint evidence before making another change.Review the immediately preceding command or configuration diff, service status, listener ownership, journal timestamps, and the exact server address queried.
ResolutionStop at this layer and correct the discrepancy before continuing. Answer, validation state, or TTL progression is inconsistent.
Security notes
- Do not expose remote-control statistics broadly; cache metadata can reveal client behavior and operational patterns.
- Do not paste private names, client addresses, keys, complete query logs, or registrar account details into public support channels. Redact evidence while retaining timestamps, response codes, flags, serials, key tags, and server identities needed for diagnosis.
Alternatives
- Use approved local metrics collection with aggregate counts and minimal query-name retention.
Stop conditions
- Do not treat cache speed as acceptance when validation or content differs.
verification
Test allowed and refused clients from real network paths
Query from one approved client and one address outside the allowed CIDR, using both UDP and TCP. The resolver must recurse for the approved source and refuse or drop every unapproved source.
Why this step matters
Policy must be observed from the network, because localhost cannot demonstrate source CIDR evaluation, routing, interface binding, or the external firewall. A negative source test is as important as a successful client.
What to understand
Run the shown approved-client commands on the client, not through an SSH session on the resolver.
Use a genuinely unapproved routed source for the negative test and inspect whether the result is REFUSED or a firewall timeout according to policy.
Test TCP separately; a UDP success does not prove the fallback transport, and a TCP success alone can hide UDP state issues.
Keep the command output with the change record. DNS is distributed and cached, so an immediate local success is only one layer of evidence; later checkpoints deliberately test authoritative behavior, delegation, validation, transport, and client-visible results separately.
Run the exact read-only checkpoint before moving on. If its evidence differs from the example, diagnose that layer instead of stacking another configuration change, restarting repeatedly, or weakening a security control to make a query appear successful.
System changes
- No persistent change; performs allowed and denied network requests and may add accepted answers to cache.
Syntax explained
+tcp- Forces the connection-oriented DNS transport used after truncation.
+comments- Shows the response code and recursion flags needed to evaluate refusal.
Values stay on this page and are never sent or saved.
dig @{{resolverAddress}} www.iana.org A +noall +comments +answer; dig @{{resolverAddress}} www.iana.org A +tcp +noall +comments +answer;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35211 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1 www.iana.org. 1200 IN A 192.0.33.8 ;; TCP setup with 10.24.0.53#53(10.24.0.53) for www.iana.org completed
Checkpoint: Prove allow and deny paths
Continue whenApproved UDP/TCP queries succeed; the unapproved host never receives a recursive answer.
Stop whenAny public or guest source receives recursion, or an approved transport fails.
If this step fails
The “Prove allow and deny paths” checkpoint does not produce the expected evidence.
Likely causeThe preceding change is incomplete, the observed system differs from the documented assumptions, or the checkpoint reached a different DNS component than intended. Expected evidence: Approved UDP/TCP queries succeed; the unapproved host never receives a recursive answer.
Compare the observed state with the documented checkpoint evidence before making another change.Review the immediately preceding command or configuration diff, service status, listener ownership, journal timestamps, and the exact server address queried.
ResolutionStop at this layer and correct the discrepancy before continuing. Any public or guest source receives recursion, or an approved transport fails.
Security notes
- Use a controlled test host; do not advertise or scan the resolver from unrelated networks.
- Do not paste private names, client addresses, keys, complete query logs, or registrar account details into public support channels. Redact evidence while retaining timestamps, response codes, flags, serials, key tags, and server identities needed for diagnosis.
Alternatives
- Use a temporary network namespace with a separately routed source when a physical denied client is unavailable.
Stop conditions
- Treat unexpected recursion for an unapproved source as an exposure incident and block rollout.
instruction
Roll out the resolver to clients in controlled stages
Change one canary host, then a small DHCP or VPN group, and only then the full network. Avoid advertising an unrelated public resolver as a secondary because clients may use it at any time and silently bypass local policy.
Why this step matters
DNS is a foundational dependency, so staged migration limits blast radius and reveals client-specific caches, VPN policies, IPv6 paths, and captive behavior before the whole fleet changes.
What to understand
A canary should exercise web, package, authentication, monitoring, and internal name lookups rather than only one dig command.
Multiple advertised resolvers are generally peers, not ordered primary and emergency values. Every advertised address must implement equivalent policy.
DHCP lease time affects rollback speed. Document renewal commands and static exceptions before changing the option.
Keep the command output with the change record. DNS is distributed and cached, so an immediate local success is only one layer of evidence; later checkpoints deliberately test authoritative behavior, delegation, validation, transport, and client-visible results separately.
Run the exact read-only checkpoint before moving on. If its evidence differs from the example, diagnose that layer instead of stacking another configuration change, restarting repeatedly, or weakening a security control to make a query appear successful.
System changes
- Changes resolver selection on canary and later managed client groups; may alter every hostname lookup made by those systems.
Syntax explained
resolvectl status- Shows per-link resolver selection and search/routing domains on systemd-resolved clients.
resolvectl query- Tests through the client's configured resolver path rather than bypassing it with dig @address.
resolvectl status; resolvectl query www.iana.org; resolvectl query resolver.home.arpaLink 2 (ens18)
Current Scopes: DNS
DNS Servers: 10.24.0.53
www.iana.org: 192.0.33.8 -- link: ens18
resolver.home.arpa: 10.24.0.53 -- link: ens18Checkpoint: Promote only a healthy canary
Continue whenThe canary uses only approved resolvers and completes representative public, private, signed, and failure-path tests.
Stop whenAny application bypasses policy, IPv6 selects another server, or rollback cannot restore service quickly.
If this step fails
The “Promote only a healthy canary” checkpoint does not produce the expected evidence.
Likely causeThe preceding change is incomplete, the observed system differs from the documented assumptions, or the checkpoint reached a different DNS component than intended. Expected evidence: The canary uses only approved resolvers and completes representative public, private, signed, and failure-path tests.
Compare the observed state with the documented checkpoint evidence before making another change.Review the immediately preceding command or configuration diff, service status, listener ownership, journal timestamps, and the exact server address queried.
ResolutionStop at this layer and correct the discrepancy before continuing. Any application bypasses policy, IPv6 selects another server, or rollback cannot restore service quickly.
Security notes
- Do not add an outside public resolver as a silent fallback; it leaks queries and bypasses local names and incident controls.
- Do not paste private names, client addresses, keys, complete query logs, or registrar account details into public support channels. Redact evidence while retaining timestamps, response codes, flags, serials, key tags, and server identities needed for diagnosis.
Alternatives
- Operate two identically controlled private resolvers and advertise both after independent failure testing.
Stop conditions
- Pause between cohorts long enough to observe cache and lease behavior.
verification
Establish monitoring, update, and trust-anchor checks
Record service, latency, validation, refusal, TCP, clock, package, and trust-anchor probes. Test them after updates and retain enough journal history to distinguish upstream failure from local policy.
Why this step matters
A resolver can remain process-active while validation, time, transport, or authority reachability is broken. Operations therefore need semantic probes in addition to service uptime.
What to understand
Run positive and broken-chain tests from a client path, not only on loopback, and retain response status without retaining complete user query history.
Package upgrades can change defaults or restart timing; repeat listener, parser, validation, and refusal acceptance after each upgrade.
Trust-anchor checks should be alertable but not auto-remediated by deleting state, because destructive repair can conceal the original cause.
Keep the command output with the change record. DNS is distributed and cached, so an immediate local success is only one layer of evidence; later checkpoints deliberately test authoritative behavior, delegation, validation, transport, and client-visible results separately.
Run the exact read-only checkpoint before moving on. If its evidence differs from the example, diagnose that layer instead of stacking another configuration change, restarting repeatedly, or weakening a security control to make a query appear successful.
System changes
- No intended persistent change; anchor maintenance may update managed metadata when a valid rollover state requires it.
Syntax explained
NTPSynchronized- Reports whether systemd considers the clock synchronized for time-sensitive validation.
--since '-15 minutes'- Bounds journal review to the current maintenance or incident window.
systemctl is-active unbound; timedatectl show -p NTPSynchronized; sudo -u unbound unbound-anchor -a /var/lib/unbound/root.key; journalctl -u unbound --since '-15 minutes' --no-pager | tail -20active NTPSynchronized=yes /var/lib/unbound/root.key has content Jul 28 11:42:13 resolver unbound[1842]: info: service stopped (unbound 1.19.2). Jul 28 11:42:13 resolver unbound[2051]: info: start of service (unbound 1.19.2).
Checkpoint: Make semantic DNS health observable
Continue whenService, time, anchor, positive validation, negative validation, TCP, and refusal probes all have owners and thresholds.
Stop whenMonitoring checks only process uptime or stores unrestricted query data without an approved retention policy.
If this step fails
The “Make semantic DNS health observable” checkpoint does not produce the expected evidence.
Likely causeThe preceding change is incomplete, the observed system differs from the documented assumptions, or the checkpoint reached a different DNS component than intended. Expected evidence: Service, time, anchor, positive validation, negative validation, TCP, and refusal probes all have owners and thresholds.
Compare the observed state with the documented checkpoint evidence before making another change.Review the immediately preceding command or configuration diff, service status, listener ownership, journal timestamps, and the exact server address queried.
ResolutionStop at this layer and correct the discrepancy before continuing. Monitoring checks only process uptime or stores unrestricted query data without an approved retention policy.
Security notes
- Restrict journals and metrics that reveal internal names, client addresses, or query patterns.
- Do not paste private names, client addresses, keys, complete query logs, or registrar account details into public support channels. Redact evidence while retaining timestamps, response codes, flags, serials, key tags, and server identities needed for diagnosis.
Alternatives
- Export aggregate Unbound metrics through a local authenticated collector without exposing the control socket remotely.
Stop conditions
- Do not close the change until a future operator can distinguish validator failure from an ordinary domain outage.
Finish line
Verification checklist
sudo unbound-checkconfThe parser reports no errors and resolves every include.dig @{{resolverAddress}} cloudflare.com A +dnssec +noall +comments; dig @{{resolverAddress}} dnssec-failed.org A +dnssec +noall +commentsThe signed name is NOERROR with AD; the deliberately broken chain is SERVFAIL without an answer.dig @{{resolverAddress}} www.iana.org A +noall +answer; dig @{{resolverAddress}} www.iana.org A +tcp +noall +answerUDP and TCP return the same current answer.dig @{{resolverAddress}} www.iana.org A +noall +commentsAn approved source receives recursion; a separately tested unapproved source receives REFUSED or no response.dig @{{resolverAddress}} resolver.home.arpa A +noall +answer; sudo unbound-checkconf | catThe home.arpa record resolves locally and configuration contains no unreviewed domain-insecure exception.Recovery guidance
Common problems and safe checks
Every signed name returns SERVFAIL immediately, including the root DNSKEY query.
Likely causeThe clock is wrong, root.key is missing or unreadable, validation modules are absent, or outbound authority traffic is blocked.
Run timedatectl status and compare UTC with a trusted source.Run sudo -u unbound test -r /var/lib/unbound/root.key and sudo -u unbound unbound-anchor -a /var/lib/unbound/root.key.Inspect journalctl -u unbound and test UDP plus TCP queries to known authoritative servers without changing validation policy.
ResolutionCorrect time, ownership, package, or transport first; re-run unbound-anchor as the service user and restart only after unbound-checkconf passes. Do not add a validation exception.
Small domains resolve but some DNSSEC-heavy names time out or intermittently SERVFAIL.
Likely causeTCP port 53, fragmented UDP, path MTU, or stateful firewall handling is broken; large responses trigger a different path.
Compare dig over normal UDP and dig +tcp from the resolver host.Inspect nftables or UFW counters and capture only DNS headers with tcpdump during an approved test.Check whether an upstream firewall forcibly redirects outbound DNS.
ResolutionPermit complete stateful UDP and TCP DNS traffic, correct MTU or interception policy, and repeat positive plus broken-chain validation.
The resolver works locally but clients time out.
Likely causeUnbound listens only on loopback, the address is absent, the firewall lacks one transport, the client is outside the access-control CIDR, or routing is asymmetric.
Inspect ip -brief address and ss -lntup '( sport = :53 )'.Run unbound-checkconf -o interface and -o access-control.Query UDP and TCP from the actual client while observing firewall counters.
ResolutionCorrect the specific listener, route, firewall, or CIDR mismatch; never replace the allowlist with 0.0.0.0/0 allow.
A new private record still returns NXDOMAIN on some clients.
Likely causeA negative answer is cached, the client is using another resolver, or the local-zone include was not loaded.
Query directly at {{resolverAddress}} and compare SOA/TTL with the client-visible response.Inspect resolvectl status or platform-equivalent client resolver configuration.Run unbound-checkconf and confirm the local-zone file is included.
ResolutionFix resolver selection or configuration, reload safely, and wait for the previously advertised negative TTL instead of repeatedly changing unrelated records.
Reference
Frequently asked questions
Does a validating resolver make every answer trustworthy?
No. It proves integrity and origin only when the zone is securely delegated and signed. Unsigned zones remain insecure rather than authenticated, and DNSSEC does not assess whether the publisher's content is benign.
Why not configure 1.1.1.1 or 8.8.8.8 as a secondary client DNS server?
Clients commonly choose any configured server rather than using the second only after hard failure. That silently bypasses local names, policy, observability, and the intended direct-recursion privacy model.
Should Pi-hole or another filter run on the same port?
Only one process can own the same address and port. Use a deliberate layered topology such as a filter on the client-facing address and Unbound on loopback port 5335, covered in the separate Pi-hole guide.
Why is IPv6 disabled in the example?
Because an incomplete IPv6 listener or allowlist can create a parallel open or bypass path. Enable it only with stable addresses, client ranges, firewall rules, and equivalent validation tests.
Recovery
Rollback
Restore clients first so they retain DNS, then restore the previous Unbound configuration or stop the new resolver. Keep evidence from the failed stage before removing it.
- Restore the previous DHCP, VPN, or static resolver addresses for the affected rollout group and renew one canary client.
- Copy /etc/unbound/unbound.conf.d/oneliners.conf and local-zone.conf plus the journal to an incident directory.
- Restore the reviewed configuration backups, run sudo unbound-checkconf, and restart Unbound only if the prior service is meant to remain.
- If retiring the resolver, stop and disable unbound, remove only the two reviewed firewall rules by their current numbered identities, and confirm port 53 is no longer exposed.
- Do not delete /var/lib/unbound/root.key merely because validation failed; first determine whether time, permissions, reachability, or stale trust state caused the problem.
Evidence