Skip to main content

Networking

Zyvor Fabric provides comprehensive virtual networking with bridge management, VLANs, port forwarding, and an enterprise-grade network security stack including firewalls, VPN mesh, NAT gateways, traffic shaping, and packet mirroring.

Two policy planes: Fabric /api/network-policies is host SDN (label→nftables). Per-VM TC/eBPF edge policy lives on FluxVM and is exposed as /api/vms/{name}/dataplane/* — see VM edge dataplane. Do not conflate the two.


VM edge dataplane (Network Fabric schema v4)​

When FluxVM runs with sandbox.dataplane.mode = "ebpf", Fabric proxies the per-VM TC/eBPF edge as first-class API, Web, and CLI (schema v4: groups, CNP, effective policy, health/ipcache/FQDN refresh).

NeedWhere
Attach pathBridged VMs (network_tap: true → TAP + netns); classifier on host vh…
Per-VM UXVM → Dataplane (Status / Policy / Effective / Stats / Flows)
Cluster UXInfrastructure → Edge Dataplane (/app/edge-dataplane)
DashboardVM dataplane capability (GET /api/capabilities → vm_dataplane)
Per-VM REST/api/vms/{name}/dataplane/{status,policy,effective,stats,flows}
Cluster REST/api/dataplane/{groups,cnp,identities,observe,health,ipcache,refresh-dns} + /api/dataplane/services… (Service Fabric v6)
CLIfabricctl dataplane … (ZYVOR_FABRIC_URL + ZYVOR_FABRIC_TOKEN on HTTPS)
Policy portsMust be tcp/PORT or udp/PORT (also icmp/0 / icmp6/0)
Maglev VIP LBService Fabric v6 (BPF schema 4) · Edge Dataplane → Services
vs other VMMsNetwork Fabric architecture comparison

Full enablement, troubleshooting, and lab UX checklist: guides/vm-drivers/fluxvm-dataplane.md.

User console: dataplane.md · edge-dataplane.md.

Tutorials: 09-edge-dataplane.md · edge-dataplane/.


Network Modes​

ModeDescriptionConfiguration
NAT (default)VMs access the internet via host NAT; not directly reachable from outside except via an explicit port forwardmode = "nat"
BridgedVM gets its own address on the local network via a dedicated network namespace, veth pair, and per-namespace DHCP server (or a static address via cloud-init)mode = "bridge"
IsolatedVMs can only communicate with each othermode = "isolated"

Bridged VMs get an address one of two ways:

  • DHCP (default) — a per-namespace dnsmasq instance leases the guest an address from a reserved pool, pinned to its MAC via --dhcp-host.
  • Static — set network_static_ip: true on the VM (or check "Assign the IP statically via cloud-init" in the Create VM wizard) to bake a fixed address into the guest's netplan config via cloud-init at boot, instead of depending on a DHCP client running inside the guest.
# /etc/zyvor-fabricd/zyvor-fabricd.toml
[network]
mode = "bridge"
bridge = "br0"

Bridges​

# Create a bridge
curl -X POST http://localhost:9095/api/network/bridges \
-H "Content-Type: application/json" \
-d '{"name": "br0"}'

# Delete a bridge
curl -X DELETE http://localhost:9095/api/network/bridges/br0

# Manual creation
sudo ip link add name br0 type bridge
sudo ip link set br0 up
sudo ip addr add 192.168.100.1/24 dev br0

Network Interfaces​

Add a NIC to a VM​

curl -X POST http://localhost:9095/api/vms/myvm/network \
-H "Content-Type: application/json" \
-d '{"name": "eth0", "bridge": "br0", "mac_address": "52:54:00:12:34:56"}'

Multiple NICs​

# Primary (NAT)
{"name": "eth0", "bridge": "virbr0"}

# Secondary (bridged)
{"name": "eth1", "bridge": "br0"}

VLANs​

# Create a VLAN on a bridge
curl -X POST http://localhost:9095/api/network/vlans \
-H "Content-Type: application/json" \
-d '{"bridge": "br0", "vlan_id": 100}'

# Assign a VM to a VLAN
curl -X POST http://localhost:9095/api/vms/myvm/network \
-H "Content-Type: application/json" \
-d '{"name": "eth0", "bridge": "br0", "vlan_id": 100}'

Port Forwarding​

# Forward host port 8080 to VM port 80
curl -X POST http://localhost:9095/api/vms/myvm/port-forwards \
-H "Content-Type: application/json" \
-d '{"protocol": "tcp", "host_port": 8080, "guest_port": 80, "guest_ip": "192.168.100.10"}'

# Remove
curl -X DELETE http://localhost:9095/api/vms/myvm/port-forwards/8080

Forwards bind 0.0.0.0 on the host, so they're reachable from any client that can reach the host over the network — not just from localhost on the host itself. Testing a forward from the same host that's serving it will bypass PREROUTING and can look broken even when it isn't; test from a separate client.

Forwards can also be set at VM creation time (Create VM wizard → Advanced Options → Expose ports, with a one-click preset for SSH on port 22) rather than added after the fact via the API above. Adding or removing a forward on a VM that's currently running restarts it to apply the change.


DNS​

[network]
enable_dns = true
domain = "Zyvor Fabric.local"
dns_servers = ["8.8.8.8", "8.8.4.4"]

VMs automatically get DNS names: myvm.Zyvor Fabric.local


Network Security Stack​

Zyvor Fabric includes a Cilium-style network security stack. All security resources use label selectors to match VMs and run background reconciliation loops to keep the system in the desired state.

Network Policies​

Label-based ingress/egress rules:

curl -X POST http://localhost:9095/api/network-policies \
-H "Content-Type: application/json" \
-d '{
"name": "allow-web",
"selector": {"match_labels": {"role": "web"}},
"ingress": [{"port": 80, "protocol": "tcp"}],
"egress": [{"port": 443, "protocol": "tcp"}],
"priority": 100,
"action": "allow"
}'

VM Firewall​

Per-VM firewall profiles and zones via nftables:

# Create a firewall profile
curl -X POST http://localhost:9095/api/firewall-profiles \
-H "Content-Type: application/json" \
-d '{
"name": "web-profile",
"rules": [
{"protocol": "tcp", "port": 80, "action": "allow"},
{"protocol": "tcp", "port": 443, "action": "allow"}
]
}'

# Assign to a VM
fabricctl firewall assign myvm --profile=web-profile

Service Mesh​

Virtual IP load-balanced services:

curl -X POST http://localhost:9095/api/services \
-H "Content-Type: application/json" \
-d '{
"name": "web-service",
"virtual_ip": "10.0.0.100",
"port": 80,
"algorithm": "round_robin",
"selector": {"match_labels": {"role": "web"}}
}'

Algorithms: round_robin, least_conn, random, ip_hash.

QoS / Traffic Shaping​

Bandwidth management with guaranteed and maximum rates:

curl -X POST http://localhost:9095/api/qos-policies \
-H "Content-Type: application/json" \
-d '{
"name": "standard-qos",
"selector": {"match_labels": {"tier": "standard"}},
"guaranteed_rate_mbps": 10,
"max_rate_mbps": 100,
"burst_kb": 1024,
"priority": 5
}'

DNS Policy​

Zone management and domain blocking:

curl -X POST http://localhost:9095/api/dns-policies \
-H "Content-Type: application/json" \
-d '{
"name": "block-ads",
"selector": {"match_labels": {"env": "production"}},
"blocked_domains": ["ads.example.com"],
"upstream_servers": ["1.1.1.1", "8.8.8.8"]
}'

VPN Mesh​

WireGuard tunnels with three topologies:

# Create a tunnel
curl -X POST http://localhost:9095/api/vpn-tunnels \
-H "Content-Type: application/json" \
-d '{
"name": "site-link",
"interface_name": "wg0",
"listen_port": 51820,
"address": "10.10.0.1/24",
"private_key_ref": "vault:wg/site-link",
"peers": [{
"public_key": "abc123...",
"endpoint": "203.0.113.5:51820",
"allowed_ips": ["10.10.0.2/32"],
"persistent_keepalive": 25
}]
}'

# Create an auto-mesh network
curl -X POST http://localhost:9095/api/vpn-networks \
-H "Content-Type: application/json" \
-d '{
"name": "dev-mesh",
"selector": {"match_labels": {"env": "dev"}},
"subnet": "10.10.0.0/24",
"topology": "full_mesh",
"listen_port": 51820
}'

Topologies: full_mesh, hub_spoke, point_to_point.

Packet Mirror​

Traffic capture for debugging and monitoring:

curl -X POST http://localhost:9095/api/mirror-sessions \
-H "Content-Type: application/json" \
-d '{
"name": "debug-capture",
"selector": {"match_labels": {"env": "staging"}},
"collector_type": "interface",
"collector_target": "mon0",
"direction": "both",
"filter": {"protocol": "tcp", "dst_port": 80}
}'

Directions: ingress, egress, both.

NAT Gateway​

Masquerade, SNAT, DNAT, and hairpin NAT via nftables:

# Masquerade
curl -X POST http://localhost:9095/api/nat-rules \
-H "Content-Type: application/json" \
-d '{
"name": "vm-internet",
"rule_type": "masquerade",
"selector": {"match_labels": {"zone": "internal"}},
"outbound_interface": "eth0"
}'

# DNAT (port forward)
curl -X POST http://localhost:9095/api/nat-rules \
-H "Content-Type: application/json" \
-d '{
"name": "web-forward",
"rule_type": "dnat",
"protocol": "tcp",
"dest_cidr": "203.0.113.1",
"dest_port": 80,
"translate_to": "10.0.0.5",
"translate_port": 8080
}'

Network Monitor​

Per-VM bandwidth tracking with threshold alerts:

curl -X POST http://localhost:9095/api/monitor-policies \
-H "Content-Type: application/json" \
-d '{
"name": "high-bandwidth-alert",
"selector": {"match_labels": {"tier": "production"}},
"thresholds": [
{"value": 100, "unit": "mbps", "direction": "rx", "severity": "warning"},
{"value": 500, "unit": "mbps", "direction": "both", "severity": "critical"}
],
"action": "log",
"sample_interval_secs": 10
}'

# View metrics and alerts
curl http://localhost:9095/api/network-metrics
curl http://localhost:9095/api/network-metrics/myvm
curl http://localhost:9095/api/bandwidth-alerts

Background Reconciliation​

All networking crates run reconciliation loops to keep the system in the desired state:

ComponentIntervalDescription
VPN Mesh30sSync WireGuard interfaces
Packet Mirror30sSync tc mirror rules
NAT Gateway30sSync nftables NAT rules
Network Monitor10sCollect metrics and evaluate thresholds

Force immediate reconciliation on any component with its /sync endpoint.


Performance​

Virtio​

Virtio network drivers are automatically used for modern Linux guests, providing near-native network performance.

Jumbo Frames​

Enable for high-throughput workloads:

sudo ip link set br0 mtu 9000

Testing​

# Individual crates
cargo test -p network-policy
cargo test -p service-mesh
cargo test -p traffic-shaping
cargo test -p dns-policy
cargo test -p vm-firewall
cargo test -p vpn-mesh
cargo test -p packet-mirror
cargo test -p nat-gateway
cargo test -p net-monitor

# All networking crates
cargo test -p vpn-mesh -p packet-mirror -p nat-gateway -p net-monitor

Troubleshooting​

# VM network
ip addr show # Inside VM
ip route show # Inside VM

# Host bridge
ip link show br0
bridge link show

# Port forwards
sudo iptables -t nat -L PREROUTING -n -v

# WireGuard tunnels
sudo wg show

# NAT rules
sudo nft list table ip zyvor-fabricd_nat

# Mirror rules
sudo tc -s qdisc show
sudo tc filter show dev tap-myvm parent ffff:

# Network counters
cat /sys/class/net/tap-myvm/statistics/rx_bytes
cat /sys/class/net/tap-myvm/statistics/tx_bytes

# VM edge dataplane (Network Fabric schema v4)
curl -sk https://127.0.0.1:9095/api/vms/NAME/dataplane/status -H "Authorization: Bearer $TOKEN"
curl -sk https://127.0.0.1:9095/api/dataplane/health -H "Authorization: Bearer $TOKEN"
curl -sk https://127.0.0.1:9095/api/dataplane/groups -H "Authorization: Bearer $TOKEN"
sudo ls /sys/fs/bpf/fluxvm/vms/
sudo cat /run/fluxvm/ebpf/vms/*/schema_version
# Full guide: docs/guides/vm-drivers/fluxvm-dataplane.md
# Tutorials: docs/tutorials/09-edge-dataplane.md · docs/tutorials/edge-dataplane/