Local DNS Resolution Failure Caused by OpenWrt Router Advertisements¶
Symptom¶
Mobile devices (Android/Pixel) on the LAN could not resolve internal
hostnames served by OPNsense/Unbound and dnsmasq, while wired clients
resolved them without issue. The phone's Wi-Fi DNS settings correctly
showed OPNsense as the DNS server, but lookups for internal hostnames
failed and public domains resolved via an unexpected upstream (8.8.8.8)
instead of the expected resolver.
Environment¶
- Firewall/router: OPNsense, using the dnsmasq DNS & DHCP plugin (not the legacy ISC DHCP + Unbound combination) for the LAN interface
- Access points: two OpenWrt devices (
prettyfly,wutanglan) configured as "dumb" bridged APs, with DHCPv4 (dhcp.lan.ignore=1) disabled on both - Client: Google Pixel phone (Android), IPv6-preferring by default
Diagnostic path¶
Ruled out, in order, before finding the actual cause:
- Android Private DNS (Settings → Network & internet → Private DNS) — confirmed off. Not the cause.
- VPN or DNS-filtering apps (AdGuard, NextDNS, etc.) intercepting DNS via Android's VPN API — none active.
- Static IP / hardcoded DNS on the Wi-Fi network config — confirmed set to DHCP, not static.
- OPNsense DHCP/DNS configuration — checked in order:
- Services → DHCPv4 → LAN: no entry (LAN was already migrated to
dnsmasq; ISC DHCP only had a leftover WAN entry)
- Services → Dnsmasq DNS & DHCP → General/DHCP ranges: DNS server
fields empty
- System → Settings → General → DNS Servers: empty and unchecked
-
/conf/config.xml:grep -A2 -B2 "8.8.8.8"returned nothing —8.8.8.8was not hardcoded anywhere in the OPNsense config - Confirmed OPNsense's DHCP lease table did list the phone, so OPNsense's dnsmasq was in fact issuing the lease (not losing a DHCP race to a second server) - A rogue/second DHCP server on the LAN — checked both OpenWrt APs'
/etc/config/dhcp; neither had8.8.8.8in config, and no evidence of a competing DHCPv4 server. - dnsmasq running on the APs themselves — this is what broke it open:
ps | grep dnsmasq
netstat -lnp | grep :53
Both APs had dnsmasq actively listening on their own LAN IPv4
address and on unique-local IPv6 addresses (fdxx:.../64 ULA and
link-local fe80::/64), even though each was intended to be a plain
bridged access point with DHCPv4 disabled.
Root cause¶
Disabling DHCPv4 on an OpenWrt interface via dhcp.lan.ignore='1' stops
the device from leasing IPv4 addresses, but does not disable
Router Advertisements (RA). RA is controlled independently by
dhcp.lan.ra, which defaults to 'server' if not explicitly set.
With RA still active (odhcpd running), both APs were advertising
themselves as a DNS resolver over IPv6 via RDNSS, regardless of the
IPv4 DHCP configuration. Android's Pixel prefers IPv6 when both stacks
are available, so it picked up an AP's own IPv6 address as its DNS
server from the RA — bypassing OPNsense's dnsmasq entirely and querying
the AP's local dnsmasq instance instead, which forwarded upstream to
8.8.8.8. Because that path is IPv6 and per-RA rather than IPv4/DHCP,
it never showed up in any of the IPv4-focused config locations checked
earlier (OPNsense's config, the AP's /etc/config/dhcp DNS fields,
Android's own DHCP/gateway details).
Confirmed on both APs:
uci get dhcp.lan.ra
# server
ps | grep odhcpd
# odhcpd running
Fix¶
On each OpenWrt AP, explicitly disable RA and DHCPv6 rather than relying
on ignore (which only covers DHCPv4):
uci set dhcp.lan.ra='disabled'
uci set dhcp.lan.dhcpv6='disabled'
uci commit dhcp
/etc/init.d/odhcpd restart
/etc/init.d/dnsmasq restart
On the client, forget and rejoin the Wi-Fi network (or toggle Wi-Fi off and on) to flush any cached RA-derived IPv6 DNS server before retesting.
Verification¶
From a terminal on the client (e.g. Termux):
dig <internal-hostname>
Confirm the responding server matches OPNsense's LAN IP and that internal hostnames resolve correctly.
Notes / prevention¶
- On OpenWrt,
dhcp.lan.ignore='1'(disable DHCPv4) and RA are separate settings. A "dumb AP" configuration needs both DHCPv4 and RA/DHCPv6 explicitly disabled to fully stop the device from answering network-configuration or DNS queries. - When troubleshooting DNS-resolves-to-wrong-server issues on dual-stack networks, check IPv6 RA/RDNSS sources as early as checking DHCPv4, especially with IPv6-preferring clients like modern Android devices — the symptom (wrong DNS server used, correct one shown in UI) looks identical to a DHCPv4 problem but lives entirely on the IPv6 side.
ps | grep dnsmasq/ps | grep odhcpdplusnetstat -lnp | grep :53on each network device is a fast way to confirm whether something is actually listening and answering, independent of what its config files claim.- This was a longstanding OPNsense dnsmasq DNS/DHCP setup (migrated from ISC DHCP + Unbound), which meant guidance assuming Unbound was authoritative for DHCP needed to be redirected mid-troubleshoot to the dnsmasq plugin instead.