fix: boxes could reach each other — isolate them at the bridge #37
No reviewers
Labels
No labels
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-triage
ready
release
scope:cli
scope:drill
scope:host
scope:installer
scope:templates
scope:tiers
stale
state:addressing
state:bots-reviewing
state:building
state:needs-human
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/box#37
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/sibling-isolation"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes the finding from the #15 audit: boxes were not isolated from each other. A live probe caught box A's SYN arriving at box B, with B answering by RST.
Why the ACL never caught it
The ACL is not wrong — it never saw the traffic. Two boxes on one bridge share an L2 segment: their frames are switched between bridge ports and never traverse the netfilter path an L3 rule lives on. So the egress drop on
10.0.0.0/8(which containsclaudenet) and the default ingress drop both looked airtight, and neither ever fired. That is exactly why the original "belt and braces" reading was plausible and wrong.The fix: an nftables bridge-family rule
The bridge family's forward hook fires exactly when a frame passes from one bridge port to another — which on
claudenetmeans box→box and nothing else. Frames addressed to the gateway are delivered locally (INPUT), and so is anything being routed out to the internet. So dropping every forwarded frame on this bridge isolates the boxes and costs them nothing. DHCP and ARP still work: they are broadcast, and the local delivery to dnsmasq happens on INPUT, not FORWARD.It lives in
claudebox-firewall.sh, so the boot unit re-applies it — the same discipline as the rest of the runtime rules.Also in this PR
dns.mode=none— a box couldgetent hosts <sibling>and get a name and address out of the gateway's dnsmasq. Blocked connections with open reconnaissance is not isolation. (Verified: public egress is unaffected.)security.ipv4_filteringdeliberately NOT adopted — it breaks the box (dockerd comes up but cannot pull or run a container). Tested on a healthy baseline, vetoed, and the reason is recorded so it isn't re-proposed.The rule this leaves behind
Isolation claims are tested, never reasoned about. The hole existed precisely because a plausible code reading said it could not.
Verify:
bash drill/drill.sh --yes→ A3 must flip fromrefused(the packet arrived) todropped.🤖 Generated with Claude Code