fix(firecracker-netpool): per-TAP anti-spoof so source-IP attribution is sound (PR #354 review)

The /31 point-to-point TAP does NOT make a guest source address
unspoofable: root in an agent VM can source another bottle's guest IP on
its own bbfc TAP. The isolation table only matched iifname class + port
(DNAT) and never bound iifname to its assigned ip saddr — so a spoofed
source was DNAT'd to the gateway and attributed to the *victim* bottle,
getting the victim's policy/tokens. Source-IP attribution was therefore
not actually sound.

Add one anti-spoof rule per slot in the isolation forward chain, before
the established/DNAT accepts: `iifname bbfcN ip saddr != <guestN> drop`.
Generated in the existing setup loop — no new dependency, ~pool_size
lines. Legit traffic (correct saddr) is unchanged; a spoofed saddr on any
bbfc TAP is dropped before it can be attributed.

Apply with a nixos-rebuild (the systemd unit re-runs this script). Codex
review blocker; the app-layer identity token (defense-in-depth) is wired
separately.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
This commit is contained in:
2026-07-16 16:09:45 -04:00
parent 0a26b8795a
commit 43c3d4408e
+14 -1
View File
@@ -166,6 +166,19 @@ _install_nft() {
# Delete-first (create empty, delete, recreate) so a re-applied `up`
# lands identical state instead of appending rules / erroring on the
# existing base chains — the setup is idempotent regardless of history.
# Anti-spoof: bind each TAP to its assigned guest IP. The /31 alone
# does NOT make the source address unspoofable — root in an agent VM
# can source another bottle's guest IP on its own bbfc TAP, and the
# gateway attributes egress/policy/tokens by source IP. So drop any
# packet whose source isn't the guest address assigned to the exact
# TAP it arrived on, before it can be attributed. One rule per slot.
local antispoof="" i
for i in $(seq 0 $((POOL_SIZE-1))); do
antispoof="${antispoof} iifname \"$(iface "$i")\" ip saddr != $(guest_ip "$i") drop
"
done
nft -f - <<EOF
table inet $TABLE {}
delete table inet $TABLE
@@ -173,7 +186,7 @@ table inet $TABLE {
chain forward {
type filter hook forward priority -10; policy accept;
iifname != "${PREFIX}*" return
ct state established,related accept
${antispoof} ct state established,related accept
ct status dnat accept
drop
}