Skip to main content
All network traffic from a sandbox flows through a host-controlled networking stack. From inside, the sandbox sees a normal network interface, but on the host side every packet is subject to policy before it goes anywhere. The sandbox’s only path to the outside world is through this stack, so blocked traffic never leaves the VM.

Network presets

The simplest way to configure networking. public_only is the default.
use microsandbox::NetworkPolicy;

// Public internet only
let sb = Sandbox::builder("web-agent")
    .image("python:3.12")
    .network(|n| n.policy(NetworkPolicy::public_only()))
    .create()
    .await?;

Port mapping

Expose ports from the sandbox to the host so services running inside the VM are accessible from your machine. In Rust, SandboxBuilder::port() and port_udp() are top-level shorthands, so you can publish ports without nesting everything inside .network(...).
let sb = Sandbox::builder("api")
    .image("python:3.12")
    .port(8080, 80)
    .port_udp(5353, 5353)
    .network(|n| n.policy(NetworkPolicy::public_only()))
    .create()
    .await?;

DNS interception

DNS queries from the guest are intercepted and resolved on the host side, which opens up a few useful controls:
  • Domain blocking by exact match or suffix (e.g. *.tracking.com).
  • Rebinding protection: if a DNS response resolves to a private IP (10.x, 172.16.x, 192.168.x, 127.x, link-local), the query is blocked. This prevents the trick where an attacker registers a public domain that points to an internal service.
  • DNS-to-IP binding: when secrets are configured, domains can be pinned to the IPs they resolved to, preventing TOCTOU attacks where DNS changes between the policy check and the actual connection.
let sb = Sandbox::builder("safe-agent")
    .image("python:3.12")
    .network(|n| n
        .policy(NetworkPolicy::public_only())
        .dns(DnsMode::Intercepted)
        .block_domain("malware.example.com")
        .block_domain("*.tracking.com")
    )
    .create()
    .await?;

How it works

Policy rules are evaluated first-match-wins. Allowed traffic goes to the real network; everything else is dropped.
  • none: no network interface at all. The guest is fully offline, though exec and fs still work since they don’t use the network.
  • public_only: blocks private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8, 169.254.0.0/16) and only allows routable public addresses. This is the default.
  • allow_all: no filtering, including access to the host machine and local network.
  • allowlist / denylist: fine-grained per-host control.