Skip to content

feat(vmm): enforce bridge MAC identity with netd - #836

Closed
kvinwang wants to merge 4 commits into
feat/secure-bridge-networkingfrom
feat/secure-bridge-phase1
Closed

feat(vmm): enforce bridge MAC identity with netd#836
kvinwang wants to merge 4 commits into
feat/secure-bridge-networkingfrom
feat/secure-bridge-phase1

Conversation

@kvinwang

Copy link
Copy Markdown
Collaborator

Stack

Summary

  • add dstack-vmm netd, a separate root networking backend with a bounded JSON-over-UDS protocol and SO_PEERCRED UID authorization
  • derive TAP and nftables table names from server-generated VM identity instead of accepting caller-selected host resource names
  • constrain netd to the root-owned bridge policy introduced by fix(vmm): authorize bridge networking requests #835 and refuse foreign same-named interfaces through full ownership aliases
  • create TAPs before QEMU, disable bridge learning, enable locked, BPDU guard, root blocking, optional port isolation, and one static FDB MAC entry
  • attach a per-TAP nftables netdev-ingress policy that checks source MAC before all exceptions, rejects VLAN/802.1ad, rogue DHCP server traffic, IPv6, and unapproved EtherTypes
  • switch protected bridge NICs to QEMU -netdev tap,ifname=...,script=no,downscript=no,vhost=off
  • roll back prepared NICs on config or process-start failure and quiesce TAPs before deleting enforcement on stop/removal
  • persist the deterministic TAP in runtime network state and fail closed on restart when alias, bridge master, bridge flags, static FDB, or nftables policy cannot be proven
  • serialize privileged operations and avoid unlinking a live netd socket

Security invariant delivered

When anti_spoof = true, QEMU cannot start until every bridge NIC has a daemon-owned deterministic TAP with host-enforced MAC/L2 policy. The VMM itself does not receive CAP_NET_ADMIN. If preparation or restart reconciliation fails, the guest remains stopped rather than running on an unprotected bridge port.

Cleanup intentionally depends on deterministic identity plus the exact ownership alias, not on the old bridge still existing or remaining allowlisted. This permits safe orphan cleanup after an administrator changes bridge policy while still refusing to modify foreign interfaces.

Configuration

[cvm.networking]
mode = "bridge"
allowed_modes = ["user", "bridge"]
bridge = "dstack-br0"
anti_spoof = true
netd_socket = "/run/dstack/netd.sock"
netd_allowed_uids = [] # empty = root only
# netd_socket_gid = 1000
isolate_bridge_ports = true

Start the backend before the VMM:

sudo dstack-vmm --config /etc/dstack/vmm.toml netd

The feature remains opt-in so #835 can merge without changing existing bridge deployments.

Verification

  • cargo test -p dstack-vmm — 63 passed
  • cargo clippy -p dstack-vmm --all-targets -- -D warnings
  • git diff --check feat/secure-bridge-networking...HEAD
  • isolated-netns kernel primitive test: bridge locked/guard/root_block/isolated, static FDB, and netdev ingress rules accepted
  • end-to-end root test with the actual built binary on a temporary host bridge:
    • start dstack-vmm netd
    • prepare creates TAP/FDB/nft policy
    • check proves enforcement state
    • remove quiesces and deletes all owned resources

Copilot AI review requested due to automatic review settings July 30, 2026 03:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants