From 91eaeffd9c79f5db2608440a62c9b96e7a4bda24 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 27 Mar 2026 11:06:33 +0000 Subject: [PATCH] Fix local-lan-zone.conf: add server: wrapper + correct local-data syntax MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bugs in the Unbound config file generation: 1. Missing server: wrapper OPNsense includes /var/unbound/etc/*.conf at the top level of unbound.conf (via include: or include-toplevel:). Server-level directives like local-zone: and local-data: must sit inside a server: {} block — without it they are outside any section and either silently ignored or rejected by unbound-checkconf. forward-zone: is a top-level section so forward_to_ctrld.conf correctly has no wrapper. Consequence: the original 'local-zone: "lan." static' without a server: wrapper was never actually applied, meaning the .lan leak prevention was not working. 2. No local-data records Even with a correct zone declaration, every .lan name not listed as local-data gets NXDOMAIN from the static zone. The previous commit added the local-data records; this commit gives them valid syntax inside the server: block. Generated file now looks like: server: local-zone: "lan." static local-data: "switch.mgmt.lan. A " local-data: "management.lan. A " local-data: "pbx.lan. A 192.168.50.10" ... https://claude.ai/code/session_01JR2EMK7rwrZJowpstcaxQ6 --- switch_backend.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/switch_backend.py b/switch_backend.py index fce77d4..bfa7fa8 100644 --- a/switch_backend.py +++ b/switch_backend.py @@ -2857,22 +2857,33 @@ def _build_unbound_lan_zone_conf(entries: list, mgmt_ip: str = "192.168.99.50") """ Build the full local-lan-zone.conf for Unbound. + OPNsense includes /var/unbound/etc/*.conf at the TOP LEVEL of unbound.conf + (either via include: or include-toplevel:). This means server-level + directives (local-zone:, local-data:) must be wrapped in a server: block. + Without the wrapper they land outside any section and are silently ignored + or cause unbound-checkconf to error. forward-zone: is a top-level section + and needs no wrapper — that's why forward_to_ctrld.conf works without one. + Declares 'lan.' as a static zone (so .lan never leaks to ControlD) and adds local-data A records for every entry in local-hostnames.json plus - the two built-in management aliases. Without these local-data lines every - .lan name that isn't listed gets NXDOMAIN — including pbx.lan and any + the two built-in management aliases. Without local-data entries every + .lan name not explicitly listed gets NXDOMAIN — including pbx.lan and any other custom hostname the user defined. """ - lines = ['local-zone: "lan." static', ""] + lines = [ + "server:", + ' local-zone: "lan." static', + "", + ] # Management PC aliases — always present for alias in ("switch.mgmt.lan", "management.lan"): - lines.append(f'local-data: "{alias}. A {mgmt_ip}"') + lines.append(f' local-data: "{alias}. A {mgmt_ip}"') # User-defined entries from local-hostnames.json for e in entries: name = e.get("name", "").strip().rstrip(".") ip = e.get("ip", "").strip() if name and ip: - lines.append(f'local-data: "{name}. A {ip}"') + lines.append(f' local-data: "{name}. A {ip}"') return "\n".join(lines) + "\n"