Skip to content

fix(pfsense): restart unbound after editing the DNS Resolver options - #160

Open
fr34aky wants to merge 1 commit into
jmcorgan:masterfrom
fr34aky:fix/pfsense-unbound-restart
Open

fr34aky wants to merge 1 commit into
jmcorgan:masterfrom
fr34aky:fix/pfsense-unbound-restart

Conversation

@fr34aky

@fr34aky fr34aky commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

fix(pfsense): restart unbound after editing the DNS Resolver options

Symptom. On pfSense Plus 26.07-RELEASE amd64 (KVM VM, Netgate
installer), fips-dns-setup wrote the .fips block, config.xml and the
regenerated /var/unbound/unbound.conf both carried it, and the helper
printed "DNS Resolver updated and restarted". Yet
drill <npub>.fips @127.0.0.1 AAAA through unbound answered NXDOMAIN
while the same query straight at the daemon (-p 5354) answered the AAAA,
and unbound-control lookup <npub>.fips showed the query going to the
root servers. fips-dns-teardown had the mirror problem: block gone from
the file, running resolver still forwarding.

Root cause. The helper called sync_unbound_service(). On this
release (and, from its shape, earlier ones) that function regenerates
unbound.conf and then calls start, which is a no-op while unbound is
already running. The running resolver never saw the new file. The unbound
log confirmed it: no restart after the config change, same pid throughout.

Fix. Call services_unbound_configure(), which is what the GUI's
Apply runs from services_unbound.php: it TERMs the running unbound,
waits for it to exit, and starts it on the regenerated configuration.
require_once("services.inc") added for it. The comment above the call
now says why it has to be this function.

Verified on the same VM, with the patched helper copied over the
installed one:

Step Before After
fips-dns-setup unbound pid unchanged; lookup → root servers; NXDOMAIN new pid; lookup → "forwarding request"; NOERROR with the AAAA
fips-dns-teardown pid unchanged; still forwarding new pid; NXDOMAIN, as it should be without the block
reboot block regenerated from config.xml; one daemon; chain answers NOERROR

Regression check. check-pfsense-pkg.sh now asserts statically that
the shipped helper calls services_unbound_configure() and not
sync_unbound_service(), with the reason in the check's comment. The
call itself needs pfSense's includes and cannot run in CI; the check
fails on the previous helper and passes on this one. A runtime test would
need a pfSense host, which is the same gap the README describes.

README. The test record now includes the Plus 26.07 amd64 VM run that
found this: install smoke, boot script lifecycle, the WAN-event reload
path, reboot, teardown and pkg delete, and what the VM did not cover
(mesh traffic, TUN under pf, CE itself). The paragraph saying no amd64
package had ever been installed is replaced accordingly.

The aarch64 hardware run on 26.03.1 reported .fips resolving through
unbound. I cannot say now whether unbound had been restarted by something
else on that box in between; the code path was the same.

@jmcorgan

Copy link
Copy Markdown
Owner

This looks right, and I would like to take it. Reading pfSense CE source: sync_unbound_service() regenerates unbound.conf and then calls start, which cannot take over from an already-running instance, while services_unbound_configure() sends TERM through the pidfile, waits, and only then regenerates and starts. That second function is what the GUI's Apply calls, so following it exactly, including the DHCP server restart it does when the system is not booting, is the right choice here rather than something narrower.

One thing I would like before merge, and I am happy to fold it in myself if you would rather not push again. The new README test record opens with the FreeBSD 16 amd64 package having been run on Plus 26.07, but master's CI does not build a FreeBSD 16 package. That one came from the job proposed in #159, built on the 16.0-CURRENT 20260907 snapshot. Please name the snapshot there, or say the package was built outside master's CI, so the record does not read as though the shipped pipeline produced it.

Two smaller things that can follow afterwards. The README should say that fips-dns-setup and fips-dns-teardown now restart the DNS Resolver, and the DHCP server with it, as the GUI's Apply does; an operator running either on a busy firewall should know that. And whichever of this and #159 lands second should reconcile the sentence saying the CE 2.8.1 package is still built and checked only, since #159 install-smokes it in CI.

This does not depend on the builder question in #157 and should not wait for it. Could you take it out of draft?

Symptom: on pfSense Plus 26.07 amd64, fips-dns-setup wrote the .fips
forward-zone into the DNS Resolver custom options, config.xml and the
regenerated /var/unbound/unbound.conf both carried it, and the helper
reported "DNS Resolver updated and restarted" — but `drill <npub>.fips`
through unbound answered NXDOMAIN, and `unbound-control lookup` showed
the query still going to the root servers. The daemon answered the same
query directly. fips-dns-teardown had the mirror problem: the block was
gone from the file while the running resolver kept forwarding.

Root cause: the helper called sync_unbound_service(), which regenerates
unbound.conf and then only *starts* unbound, a no-op while an instance
is already running, so the running resolver never saw the new file.

Fix: call services_unbound_configure(), which is what the GUI's Apply
runs (services_unbound.php): it TERMs the running unbound, waits, and
starts it on the regenerated configuration. Verified on the same VM:
teardown and setup each produce a new unbound pid, `unbound-control
lookup` reports "forwarding request", and the full chain answers
NOERROR; after a reboot the block is regenerated from config.xml and the
chain still answers.

Regression check: check-pfsense-pkg.sh now asserts, statically, that the
shipped helper calls services_unbound_configure() and not
sync_unbound_service(); the call itself needs pfSense's includes and
cannot run in CI. The README's test record gains the Plus 26.07 amd64 VM
run that found this.
@fr34aky
fr34aky marked this pull request as ready for review September 17, 2026 20:10
@fr34aky
fr34aky force-pushed the fix/pfsense-unbound-restart branch from 59cea4d to 6777a00 Compare September 17, 2026 20:10
@fr34aky

fr34aky commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

Done, in the same commit: the README test record now says the FreeBSD 16 amd64 package was built outside master's CI, on the 16.0-CURRENT 20260907 snapshot, before listing what the Plus 26.07 run covered. Nothing else in the diff changed. The two README follow-ups (that fips-dns-setup and fips-dns-teardown restart the DNS Resolver and the DHCP server with it, and the CE 2.8.1 "built and checked only" sentence) I will take with whichever of this and #159 lands second.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants