Files
hq/01-RESEARCH/033-split-dns-with-a-vpn-client/00-overview.md
T
jochen 478a198e9a
mesh/merge-gate pass: the change touches no module of the mesh's graph
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request
ADR 0247: a machine with a VPN client routes names by domain, through a resolver of its own
Research 033 measured the laptop's VPN client and the mesh overwriting each
other's resolver file in nine of nine sessions, each time cutting off one
kind of name. The operator chose a resolver module on a node seat of its
own, installed only where something requires split-dns, with the VPN
client's module carrying the adapter. Graduates research 033 into to-be 50,
and amends connectivity §2, to-be 48 §10, the seats and the glossary.
2026-10-07 21:33:48 +02:00

80 lines
4.8 KiB
Markdown

---
status: graduated
initiated: 2026-10-07
became:
- 02-DECISIONS/0247-a-machine-with-a-vpn-client-routes-names-by-domain-through-a-resolver-of-its-own.md
- 03-DESIGN/01-to-be/50-split-dns-on-a-machine-with-a-vpn-client.md
touches:
- 02-DECISIONS/0223-the-mesh-has-two-resolvers-and-a-machine-lists-only-them.md
- 02-DECISIONS/0117-a-machines-uplink-is-a-seat.md
- 03-DESIGN/01-to-be/08-connectivity.md
- the node-uplink seat and its holders
- the node-engine's reconcile of a file another program rewrites
---
# 033 — Split DNS with a VPN client
## What is investigated
How a machine of the mesh resolves three kinds of name at once — the mesh's (`*.internal`), a
corporate network's reached through a VPN client, and public ones — when the VPN client writes
`/etc/resolv.conf` itself.
[ADR 0223](../../02-DECISIONS/0223-the-mesh-has-two-resolvers-and-a-machine-lists-only-them.md) gives
every machine one resolver file listing the mesh's two resolvers and nothing else, written by the holder
of the machine's uplink ([ADR 0117](../../02-DECISIONS/0117-a-machines-uplink-is-a-seat.md)). On the
laptop, a corporate VPN client replaces that file when it connects, with its own servers and eight search
domains. The node-engine finds the file changed and writes the mesh's back on its next reconcile. From
then on, for the rest of the session, the corporate names do not resolve; in the minutes before it, the
mesh's names did not. Neither program knows the other exists.
The questions:
1. **How the VPN client sets DNS** on Linux: does it overwrite the file, use `resolvconf`, or talk to
systemd-resolved or NetworkManager; what it backs up and restores; whether it re-asserts its file.
2. **What it pushes**: how many servers, which domains, over which link, and what routes.
3. **How often the two collide** on the live mesh, and what each collision costs.
4. **The options**: per-link routing in systemd-resolved, adding the VPN's servers to the mesh's file,
forwarding the corporate domains from the mesh's resolvers, standing back while the VPN is up, and
any other — and what each means for ADR 0223 and for the machines that run no VPN.
## Why
The operator uses the VPN for work, every working day. While it is up the laptop is either cut off from
the mesh (agents saw lookups fail) or cut off from the corporate network, depending on which program
wrote the file last. A rule of the mesh that a machine's own work program silently breaks — or that
breaks the machine's owner's work — is a rule that cannot be kept as stated.
A sibling decision proposed alongside this effort, ADR 0241 (machine network health), makes the
node-engine detect and report an outside writer of the resolver file. That says the fault; this effort
asks how it stops being one.
## What it touches
ADR 0223's rule that a machine lists only the mesh's resolvers, and its rejection of a local forwarder;
ADR 0117's list of what an uplink holder declares; the networkmanager module (the uplink holder on the
laptop); the node-engine's correction of a file changed on the machine; connectivity §2.
## Where it stands
Evidence gathered read-only on the laptop and options weighed, 2026-10-07:
- [01 — The evidence](01-evidence.md): the VPN client always *moves* the resolver file aside and writes
its own (two servers, eight search domains), restores its backup on disconnect, and never re-asserts;
it does not configure systemd-resolved or NetworkManager per link on this machine. In every one of the
nine sessions since the node-engine's journal begins, the node-engine wrote the mesh's file back within
1 s to 3.5 min; once the VPN client's restore of a stale backup was itself corrected.
- [02 — Options](02-options.md): six, from systemd-resolved per-link routing to replacing the VPN
client.
- [03 — Recommendation](03-recommendation.md): on a machine that declares a VPN client, the uplink's
holder runs systemd-resolved as a local router on the machine's private address, and hands it the
VPN's servers and domains the moment the VPN client writes them; every other machine is unchanged.
A proposed decision text with how each rule is checked.
**Graduated 2026-10-07** into [ADR 0247](../../02-DECISIONS/0247-a-machine-with-a-vpn-client-routes-names-by-domain-through-a-resolver-of-its-own.md)
and [to-be 50](../../03-DESIGN/01-to-be/50-split-dns-on-a-machine-with-a-vpn-client.md). The mechanism is
the recommendation's: systemd-resolved routing the VPN's domains over its link. Who runs it differs, by
the operator's decision. The resolver is a module of its own on a node seat, `node-resolver`, rather than
part of the uplink's holder, which has two forms. The VPN client's module carries the adapter, so no
setting declares a VPN client. The interim *defer* setting is not adopted. The record says why.