Decide whether aqomui should manage split-horizon DNS exemptions #34

Closed
opened 2026-08-17 16:57:02 -04:00 by mysticalsoap · 4 comments
Owner

Setting ~. on the tunnel is what closes the DNS leak, and it also sends
every lookup into the tunnel -- including names a local resolver answers
differently.

Confirmed on a real network: with ~. set, an internal host resolving to a LAN
address via the local resolver resolved to its public address instead and became
unreachable.

resolved prefers the most specific matching domain, so the remedy is a narrower
routing domain on the physical link (~internal.example on the LAN interface),
which then outranks ~. for that suffix.

That is per-network configuration aqomui cannot guess. But leaving it undocumented
means every split-horizon user hits this and has no obvious way to diagnose it.

Options: a "keep these domains off the tunnel" setting, documentation only, or
making ~. opt-in. Needs a decision.

Setting `~.` on the tunnel is what closes the DNS leak, and it also sends *every* lookup into the tunnel -- including names a local resolver answers differently. Confirmed on a real network: with `~.` set, an internal host resolving to a LAN address via the local resolver resolved to its public address instead and became unreachable. resolved prefers the most specific matching domain, so the remedy is a narrower routing domain on the physical link (`~internal.example` on the LAN interface), which then outranks `~.` for that suffix. That is per-network configuration aqomui cannot guess. But leaving it undocumented means every split-horizon user hits this and has no obvious way to diagnose it. Options: a "keep these domains off the tunnel" setting, documentation only, or making `~.` opt-in. Needs a decision.
Author
Owner

Status after the 2026-08-19 DNS/bypass wave (#58, #61, #63) — this issue is untouched but its landscape shifted:

  • The bypassed-apps side of split-horizon is now separable: with #58 merged, bypassed port-53 clients resolve through the bypass dnsmasq over the physical link, so setting alt_dns to the LAN resolver gives them split-horizon answers today (#60 tracks doing that automatically). What remains here is the non-bypassed system: ~. on the tunnel still routes internal names to the tunnel resolver.
  • New constraint found in the service log: OpenVPN 2.7 ships a dns-updown hook that applies the pushed DNS to the tun link via resolved on its own ("setting DNS using resolvconf", exit 0). aqomui's set_dns is no longer the only writer of tunnel DNS state — any decision here has to either coexist with that hook or disable it explicitly (--dns-updown disable).
  • #59 (double-tunnel: both tunnels claim ~.) is the same decision in another form — one policy should own who gets the default routing domain.

Workaround for split-horizon users meanwhile, same shape as the reporter's remedy: a narrower routing domain on the physical link outranks the tunnel's ~. for that suffix.

Status after the 2026-08-19 DNS/bypass wave (#58, #61, #63) — this issue is untouched but its landscape shifted: - The bypassed-apps side of split-horizon is now separable: with #58 merged, bypassed port-53 clients resolve through the bypass dnsmasq over the physical link, so setting `alt_dns` to the LAN resolver gives them split-horizon answers today (#60 tracks doing that automatically). What remains here is the non-bypassed system: `~.` on the tunnel still routes internal names to the tunnel resolver. - New constraint found in the service log: OpenVPN 2.7 ships a `dns-updown` hook that applies the pushed DNS to the tun link via resolved *on its own* ("setting DNS using resolvconf", exit 0). aqomui's `set_dns` is no longer the only writer of tunnel DNS state — any decision here has to either coexist with that hook or disable it explicitly (`--dns-updown disable`). - #59 (double-tunnel: both tunnels claim `~.`) is the same decision in another form — one policy should own who gets the default routing domain. Workaround for split-horizon users meanwhile, same shape as the reporter's remedy: a narrower routing domain on the physical link outranks the tunnel's `~.` for that suffix.
Author
Owner

Decision: split-horizon support is the existing alternative-DNS setting pointed at the local resolver, documented — no new feature.

The supported path: set "Use always" with the split-horizon resolver first and a public fallback second (e.g. 192.168.0.205, 9.9.9.9). Every lookup then goes to the resolver that is the horizon, on every network, and the second slot covers it being down. The plumbing is already coherent: alt_dns disables OpenVPN's dns-updown hook, so aqomui's set_dns is the sole writer.

Live-verified 2026-08-20 on a real split-horizon LAN (AdGuard rewrites *.example.com to a LAN address; no suffix routing domain on the physical link to mask the result): with the tunnel up, tun_aqomui carries both servers plus ~., and an internal name resolves to its LAN address.

Options rejected:

  • Per-domain exemption setting ("keep these domains off the tunnel"): solves the same problem with per-network config aqomui has to manage, plus a firewall question the alt-DNS path sidesteps. Not worth it while the zero-code path works.
  • Making ~. opt-in: reopens the DNS leak ensure_default_route_domain exists to close. Off the table.

Riders:

  • Firewall interaction: a LAN DNS server needs LAN↔LAN traffic allowed — the default ipv4local rules ACCEPT that unless block-LAN is set. Untested live; the firewall is currently unsupported (#87), so it gets verified there, not here.
  • Bypassed apps already get split-horizon answers post-#58 (bypass dnsmasq forwards the same alt servers over the physical link). #60 tracks following the physical link's own DNS automatically; a "use this network's DNS" toggle for the main tunnel is deferred to that same machinery.
  • #59 (double-tunnel ~. ownership) stays its own low-urgency issue.

Remaining work before close: a README section on the failure mode and the recipe.

Decision: split-horizon support is the existing alternative-DNS setting pointed at the local resolver, documented — no new feature. **The supported path**: set "Use always" with the split-horizon resolver first and a public fallback second (e.g. `192.168.0.205`, `9.9.9.9`). Every lookup then goes to the resolver that *is* the horizon, on every network, and the second slot covers it being down. The plumbing is already coherent: `alt_dns` disables OpenVPN's dns-updown hook, so aqomui's `set_dns` is the sole writer. **Live-verified 2026-08-20** on a real split-horizon LAN (AdGuard rewrites `*.example.com` to a LAN address; no suffix routing domain on the physical link to mask the result): with the tunnel up, `tun_aqomui` carries both servers plus `~.`, and an internal name resolves to its LAN address. **Options rejected**: - *Per-domain exemption setting* ("keep these domains off the tunnel"): solves the same problem with per-network config aqomui has to manage, plus a firewall question the alt-DNS path sidesteps. Not worth it while the zero-code path works. - *Making `~.` opt-in*: reopens the DNS leak `ensure_default_route_domain` exists to close. Off the table. **Riders**: - Firewall interaction: a LAN DNS server needs LAN↔LAN traffic allowed — the default `ipv4local` rules ACCEPT that unless block-LAN is set. Untested live; the firewall is currently unsupported (#87), so it gets verified there, not here. - Bypassed apps already get split-horizon answers post-#58 (bypass dnsmasq forwards the same alt servers over the physical link). #60 tracks following the physical link's own DNS automatically; a "use this network's DNS" toggle for the main tunnel is deferred to that same machinery. - #59 (double-tunnel `~.` ownership) stays its own low-urgency issue. Remaining work before close: a README section on the failure mode and the recipe.
Author
Owner

Amendment from continued live testing: "the second slot covers it being down" oversold the fallback. A ping-restart reconnect rotated systemd-resolved to 9.9.9.9, where it stuck — silently serving public answers for internal names — because resolved only returns to the primary when the fallback fails, and re-applying an identical server list (which set_dns does on every reconnect) does not reset its selection. Forcing a changed list does. Documented as a caveat in #94. If that silent degradation turns out to matter in practice, an aqomui-side re-pin after CONNECTED settles would be its own small issue.

Amendment from continued live testing: "the second slot covers it being down" oversold the fallback. A ping-restart reconnect rotated systemd-resolved to 9.9.9.9, where it stuck — silently serving public answers for internal names — because resolved only returns to the primary when the *fallback* fails, and re-applying an identical server list (which set_dns does on every reconnect) does not reset its selection. Forcing a *changed* list does. Documented as a caveat in #94. If that silent degradation turns out to matter in practice, an aqomui-side re-pin after CONNECTED settles would be its own small issue.
Author
Owner

Follow-up on the deferred idea: a "use this network's DNS" toggle for the main tunnel is rejected, not deferred. It deliberately builds the leak shape — tunneled traffic's DNS traveling a less-private path than the traffic it describes — and the per-app as-if-VPN-off need is already covered by bypass (#60/#97). No issue filed; this note is the record.

Follow-up on the deferred idea: a "use this network's DNS" toggle for the main tunnel is rejected, not deferred. It deliberately builds the leak shape — tunneled traffic's DNS traveling a less-private path than the traffic it describes — and the per-app as-if-VPN-off need is already covered by bypass (#60/#97). No issue filed; this note is the record.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
mysticalsoap/aqomui#34
No description provided.