Networking
Each vmsan microVM gets its own TAP network device with a /30 subnet (198.19.{slot}.0/30). You can control outbound network access with policies.
vmsan_<vmId>) with FORWARD, prerouting, and postrouting chains.Set a network policy at creation
Use the --network-policy flag when creating a VM:
# Allow all outbound traffic (default)
vmsan create --network-policy allow-all
# Block all outbound traffic
vmsan create --network-policy deny-all
# Custom policy with allowed domains
vmsan create --network-policy custom --allowed-domain "*.github.com,npmjs.org"
Available policies
| Policy | Description |
|---|---|
allow-all | Unrestricted outbound access (default) |
deny-all | No outbound access |
custom | Granular control with domain and CIDR allowlists |
custom when you specify --allowed-domain, --allowed-cidr, or --denied-cidr.Allow specific domains
Restrict outbound traffic to specific domains:
vmsan create --allowed-domain "api.example.com,*.github.com"
Wildcard * matches subdomains. DNS resolution is handled by a host-side resolver to prevent DNS bypass.
Allow or deny CIDR ranges
Control access by IP address ranges:
# Allow specific ranges
vmsan create --allowed-cidr "10.0.0.0/8,192.168.1.0/24"
# Deny specific ranges (takes precedence over all allows)
vmsan create --denied-cidr "10.0.0.0/8"
Forward ports to a VM
Expose VM ports to the host:
vmsan create --publish-port 8080,3000
This sets up DNAT rules to forward traffic from the host ports to the VM.
Limit bandwidth
Cap the outbound bandwidth per VM:
vmsan create --bandwidth 50mbit
Update a policy on a running VM
Change the network policy without restarting:
vmsan network <vm-id> --network-policy deny-all
vmsan network <vm-id> --network-policy custom --allowed-domain "api.example.com"
Security defaults
Since 0.2.0, vmsan applies a strict security baseline to all VMs by default:
ICMP blocked
All ICMP traffic from VMs is blocked by default. This prevents ICMP tunneling, a technique for exfiltrating data through echo requests and replies. ICMP type 3 (destination unreachable / fragmentation needed) is still accepted via ct state related for established connections, preserving Path MTU Discovery (PMTUD) for active TCP flows.
UDP blocked (except DNS)
All UDP traffic is blocked by default, except for DNS (port 53). This prevents UDP-based data exfiltration. DNS queries are forwarded to the configured resolvers via DNAT. Applications that rely on UDP (QUIC/HTTP3, game servers, streaming protocols) will not work from inside VMs.
DNS bypass prevention
To prevent VMs from bypassing DNS filtering, the following are blocked:
- DoT (DNS-over-TLS): TCP port 853
- DoH (DNS-over-HTTPS): TCP port 443 to known resolver IPs (Google, Cloudflare, Quad9, OpenDNS, AdGuard, CleanBrowsing)
- DoQ (DNS-over-QUIC): UDP ports 443 and 8853 (covered by the UDP default-deny)
Cross-VM isolation
Traffic to internal subnets is blocked to prevent VMs from reaching each other:
| Subnet | Purpose |
|---|---|
198.19.0.0/16 | VM link subnet (guest/host IPs) |
172.16.0.0/16 | Legacy VM address block |
10.200.0.0/16 | Veth transit subnet |
10.90.0.0/16 | Future mesh subnet (defense-in-depth) |
Reserved ports
The following port ranges are reserved for future DNS and SNI proxy functionality (planned for 0.3.0) and cannot be used as published ports:
| Range | Purpose |
|---|---|
10053-10307 | DNS proxy (one port per VM slot) |
10443-10697 | SNI proxy (one port per VM slot) |
10080-10334 | HTTP proxy (one port per VM slot) |
Disable network namespace isolation
By default, each VM runs in its own network namespace. Disable this with:
vmsan create --no-netns
Troubleshooting
Check nftables support
vmsan doctor detects nftables kernel support and host firewalls. Run it to verify your system is properly configured:
sudo vmsan doctor
Host firewall interference
If the host runs ufw or firewalld, their FORWARD chains may interfere with vmsan traffic. In nftables, multiple tables each have independent chains at the same hook -- if any table's chain drops a packet, it's dropped.
To fix this, add explicit allow rules for vmsan traffic in your host firewall. For example, with ufw:
sudo ufw allow in on veth-h-+
sudo ufw route allow in on veth-h-+
Falling back to iptables
If nftables fails on your system, you can fall back to the legacy iptables backend:
VMSAN_LEGACY_IPTABLES=1 sudo vmsan start <vmId>
This env var is a temporary escape hatch and will be removed in 0.3.0.
Inspecting active rules
To inspect the nftables rules for a specific VM:
sudo nft list table ip vmsan_<vmId>
To list all vmsan-managed tables:
sudo nft list tables | grep vmsan