From 2c03624013d98812c2c3c700ce132c867ebe9184 Mon Sep 17 00:00:00 2001 From: claude-hdb Date: Tue, 14 Jul 2026 11:58:36 +0000 Subject: [PATCH] =?UTF-8?q?fix(doctor):=20the=20gateway=20does=20not=20ans?= =?UTF-8?q?wer=20ping=20=E2=80=94=20by=20design,=20so=20stop=20asking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit claudebox-firewall.sh drops everything from a box to the host except DNS (53) and DHCP (67); ICMP to 10.87.0.1 dies in that trailing drop on every healthy host. The doctor used exactly that ping as its routing probe, so it reported 'cannot even reach the gateway' — and a NOT-fit- to-drill verdict — on a host whose very next line proved DNS working through that same gateway. Probe routing the way the contract states it: a box reaches the public internet. curl to 1.1.1.1 by address, reusing the one probe for the DNS-failure diagnosis instead of running it twice. --- drill/doctor.sh | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drill/doctor.sh b/drill/doctor.sh index 718c777..ee20e23 100755 --- a/drill/doctor.sh +++ b/drill/doctor.sh @@ -212,17 +212,23 @@ if [ -n "$probe" ] && [ "$FIX" != 1 ]; then inf "probing inside '$probe' — this separates DNS from routing, which is the whole question:" inf "its resolv.conf: $(timeout -k 5 20 incus exec "$probe" -- sh -c 'grep -m2 nameserver /etc/resolv.conf' /dev/null | tr '\n' ' ')" - timeout -k 5 20 incus exec "$probe" -- ping -c1 -W2 10.87.0.1 /dev/null 2>&1 \ - && ok "reaches the gateway (10.87.0.1) — routing is fine" \ - || no "cannot even reach the gateway — this is routing, not DNS" + # Routing is probed by ADDRESS against the public internet, NOT by pinging + # the gateway: claudebox-firewall.sh drops everything from a box to the host + # except DNS/DHCP, so ICMP to 10.87.0.1 fails BY DESIGN on a healthy host. + # A gateway ping here is a check that can only ever lie. + if timeout -k 5 25 incus exec "$probe" -- curl -sS -m 10 -o /dev/null https://1.1.1.1 /dev/null; then + routing=1; ok "reaches 1.1.1.1 by address — egress routing is fine" + else + routing=0; no "cannot reach 1.1.1.1 by address — egress routing is broken (this is not DNS)" + fi if timeout -k 5 25 incus exec "$probe" -- getent hosts deb.debian.org /dev/null 2>&1; then ok "resolves deb.debian.org — DNS works" else no "CANNOT resolve deb.debian.org — this is exactly what kills cloud-init on every cold mint" - # Does the box reach the internet at all WITHOUT DNS? If yes, the fault is - # purely name resolution — i.e. the forwarder, i.e. issue #33. - if timeout -k 5 25 incus exec "$probe" -- curl -sS -m 10 -o /dev/null https://1.1.1.1 /dev/null; then + # Egress by address was probed above. If it worked, the fault is purely + # name resolution — i.e. the forwarder, i.e. issue #33. + if [ "$routing" = 1 ]; then inf "…but it CAN reach 1.1.1.1 by address. So egress works and only NAME RESOLUTION is broken:" inf "the fault is the forwarder the box inherits from the host — issue #33." inf "test the fix: bash drill/doctor.sh --pin-dns then re-run the drill" -- 2.45.2