fix: pin claudenet's resolver — a box's DNS is not a function of the host's VPN #45

Merged
dan-claude-bot merged 1 commit from fix/pin-claudenet-resolver into main 2026-07-14 12:22:47 +00:00
2 changed files with 17 additions and 2 deletions

View file

@ -182,9 +182,10 @@ else
no "the host resolves via a CGNAT/Tailscale resolver ($hostns), and boxes INHERIT it — see issue #33"
inf "· box DNS breaks whenever the tailnet's resolver does (this is what kills cold mints)"
inf "· and tailnet names RESOLVE from inside a box, though its ACL blocks connecting to them"
inf "fix + test: bash drill/doctor.sh --pin-dns"
inf "fix: re-run ~/.local/share/claudebox/host/setup-host.sh (it pins the resolver)"
inf " or quick-test the pin alone: bash drill/doctor.sh --pin-dns"
else
inf "boxes inherit the host's resolver (unpinned). Fine while it is stable; see issue #33."
inf "boxes inherit the host's resolver (unpinned — setup-host.sh pins this now; re-run it)"
fi
fi

View file

@ -46,6 +46,20 @@ incus network set claudenet security.acls=claude-isolate \
# forwarding for public names is unaffected (verified live).
incus network set claudenet dns.mode=none
# A box's resolver must not be a function of the host's VPN posture (#33).
# The bridge's dnsmasq forwards to whatever sits in the HOST's /etc/resolv.conf
# at that moment. On a Tailscale/VPN host that is MagicDNS: box DNS flaps with
# the tailnet (this is what killed cold mints), and tailnet peer names and
# split-DNS zones RESOLVE from inside a box — name-level reconnaissance of a
# private network, the same shape as the sibling enumeration closed above.
# no-resolv detaches dnsmasq from the host's resolver entirely; server= pins a
# stable public upstream (override: BOX_DNS="ip ip…"). raw.dnsmasq is the
# lever — the bridge has no first-class upstream key. Verified live on the
# drill host: pin applied, box resolves, cold mint survives.
BOX_DNS="${BOX_DNS:-1.1.1.1 8.8.8.8}"
incus network set claudenet raw.dnsmasq \
"$(printf 'no-resolv\n'; for s in $BOX_DNS; do printf 'server=%s\n' "$s"; done)"
# Sibling isolation itself is NOT an ACL rule — an L3 ACL never sees frames
# switched between two ports of one bridge. It lives in claudebox-firewall.sh
# as an nftables bridge-family rule. See the comment there; it is the reason