Skip to main content
See Networking for network policies, DNS, TLS, and port publishing.

NetworkPolicy

NetworkPolicy::builder()

Create a NetworkPolicyBuilder to configure rules and per-direction defaults. The first matching rule wins in each direction. build() validates string inputs (.ip, .cidr, .domain, .domain_suffix) and returns a BuildError for invalid input.

Returns

Empty builder.

NetworkPolicy::none()

No network access: deny everything in both directions, no rules. This is the policy set by SandboxBuilder::disable_network().

NetworkPolicy::allow_all()

Unrestricted network access: allow everything in both directions, no rules.

NetworkPolicy::from_profiles()

Build a deny-by-default policy from composable NetworkProfile values. Duplicate profiles are ignored, the generated rules use canonical Public, Private, Host order, and every non-empty profile set receives exactly one narrow gateway DNS rule. An empty profile set permits no egress and adds no DNS. Ingress defaults to allow, preserving published-port behavior.

Instance methods

These methods consume self and return a modified policy, so they chain off a profile or a built policy. Each prepends its rules, so a later deny outranks a catch-all allow like allow public under first-match-wins. All return Result<NetworkPolicy, DomainNameError> because the names are parsed eagerly.

policy.allow_domain()

Prepend a single allow-Domain egress rule. Single-name sugar over allow_domains().

policy.deny_domain()

Prepend a single deny-Domain egress rule. Single-name sugar over deny_domains().

policy.allow_domains()

Prepend one allow-Domain egress rule per name.

Parameters

namesIntoIterator<Item = AsRef<str>>
Exact domain names.

policy.deny_domains()

Prepend one deny-Domain egress rule per name. Prepending lets the denies outrank catch-all allows.

policy.allow_domain_suffix()

Prepend a single allow-DomainSuffix egress rule. Single-suffix sugar over allow_domain_suffixes().

policy.deny_domain_suffix()

Prepend a single deny-DomainSuffix egress rule. Single-suffix sugar over deny_domain_suffixes().

policy.allow_domain_suffixes()

Prepend one allow-DomainSuffix egress rule per suffix. Suffixes match the apex domain and every subdomain (label-aligned).

policy.deny_domain_suffixes()

Prepend one deny-DomainSuffix egress rule per suffix.

NetworkPolicyBuilder

Fluent builder for NetworkPolicy.

policy.default_deny()

Set both default_egress and default_ingress to Deny.

policy.default_allow()

Set both default_egress and default_ingress to Allow.

policy.default_egress()

Set the action when no egress rule matches.

Parameters

actionAction
Default action for egress.

policy.default_ingress()

Set the action when no ingress rule matches.

Parameters

actionAction
Default action for ingress.

policy.egress()

Sugar for rule() with direction pre-set to Egress.

policy.ingress()

Sugar for rule() with direction pre-set to Ingress.

policy.any()

Sugar for rule() with direction pre-set to Any. Rules committed inside apply in both directions.

policy.rule()

Open a multi-rule batch closure. Direction must be set inside via .egress(), .ingress(), or .any() before any rule-adder, otherwise build() returns BuildError::DirectionNotSet.

policy.build()

Consume the builder and produce a NetworkPolicy. Lazy-parses every .ip() / .cidr() / .domain() / .domain_suffix() input and validates the direction-set and ICMP-egress-only invariants. It also emits a tracing::warn! for each shadowed rule pair, meaning a rule fully covered by an earlier one in the same direction. The shadow check covers only Ip / Cidr / Group destinations. Builds still succeed when a shadow is detected. Returns the first BuildError encountered.

Returns

Validated policy.

RuleBuilder

Builder for one policy-rule batch.

rule.egress()

Set direction to Egress for subsequent rule-adders. Last-write-wins.

rule.ingress()

Set direction to Ingress for subsequent rule-adders. Last-write-wins.

rule.any()

Set direction to Any for subsequent rule-adders. Rules committed after this apply in both directions. Last-write-wins.

rule.tcp()

Add Tcp to the protocols set.

rule.udp()

Add Udp to the protocols set.

rule.icmpv4()

Add Icmpv4 to the protocols set. Egress-only: an ICMP protocol on an Ingress or Any rule fails build with BuildError::IngressDoesNotSupportIcmp.

rule.icmpv6()

Add Icmpv6 to the protocols set. Egress-only; same rule as icmpv4().

rule.port()

Add a single port to the ports set. Always guest-side (egress destination port / ingress listening port).

Parameters

portu16
Port number.

rule.port_range()

Add an inclusive port range.

Parameters

lou16
Lower bound (inclusive).
hiu16
Upper bound (inclusive). lo > hi records BuildError::InvalidPortRange.

rule.ports()

Add multiple single ports. Equivalent to calling port() once per element.

rule.allow_public()

Commit an allow rule for the Public group: every IP not in another named category. A matching deny_public() exists for each allow_* group adder below.

rule.allow_private()

Allow the Private group (RFC1918 + ULA + CGN).

rule.allow_loopback()

Allow the Loopback group (127.0.0.0/8, ::1): the guest’s own loopback, not the host. To reach a service on the host’s localhost use allow_host() instead. See the loopback-vs-host watch-out.
Allow the LinkLocal group (169.254.0.0/16, fe80::/10). Excludes the metadata IP 169.254.169.254.

rule.allow_meta()

Allow the Metadata group (169.254.169.254). Dangerous on cloud hosts: exposes IAM credentials.

rule.allow_multicast()

Allow the Multicast group (224.0.0.0/4, ff00::/8).

rule.allow_host()

Allow the Host group: per-sandbox gateway IPs that back host.microsandbox.internal. This is the right shortcut for “let the sandbox reach my host’s localhost”, not allow_loopback().

rule.deny_public()

Deny the Public group. Per-group deny_* adders mirror the allow_* set: deny_private(), deny_loopback(), deny_link_local(), deny_meta(), deny_multicast(), and deny_host().

rule.allow_local()

Commit three allow rules atomically: Loopback + LinkLocal + Host. Each uses the closure’s current state. Metadata is intentionally not included; opt in via allow_meta() separately.

rule.deny_local()

Commit three deny rules atomically: Loopback + LinkLocal + Host. Metadata is intentionally not included.

rule.allow_domains()

Add one allow-Domain rule per name, inheriting the closure’s current direction / protocol / port state. Lazy-parse: invalid names surface as BuildError::InvalidDomain from build().

rule.deny_domains()

Add one deny-Domain rule per name.

rule.allow_domain_suffixes()

Add one allow-DomainSuffix rule per suffix.

rule.deny_domain_suffixes()

Add one deny-DomainSuffix rule per suffix.

rule.allow()

Begin an explicit-destination rule with action Allow. The returned RuleDestinationBuilder requires exactly one destination call to commit; dropping it without one adds no rule.

rule.deny()

Begin an explicit-destination rule with action Deny.

RuleDestinationBuilder

Builder for a rule destination.

destination.ip()

Commit with Destination::Cidr of the IP as /32 (v4) or /128 (v6). The string is parsed at build(); invalid values surface as BuildError::InvalidIp.

destination.cidr()

Commit with Destination::Cidr. Invalid values surface as BuildError::InvalidCidr.

destination.domain()

Commit with Destination::Domain. Matches only when a cached hostname for the remote IP equals this name (after canonicalization).

destination.domain_suffix()

Commit with Destination::DomainSuffix. Matches the apex domain itself and any subdomain. A single-label suffix (e.g. com) is rejected at build as BuildError::InvalidDomain.

destination.group()

Commit with Destination::Group for callers who already hold a DestinationGroup value.

destination.any()

Commit with Destination::Any: matches every remote.

NetworkBuilder

Builder for the sandbox’s network stack, used in SandboxBuilder::network(|n| n...). Every setter returns Self, so calls chain. Errors accumulated by nested builders cascade up: the outermost SandboxBuilder::build() surfaces them as MicrosandboxError::NetworkBuilder(BuildError).

network.policy()

Set the network access policy. Pass a profile-composed or builder-constructed NetworkPolicy.

Parameters

Access policy.

network.port()

Publish a TCP port from the sandbox to the host. The default host bind address is 127.0.0.1. Equivalent to SandboxBuilder::port().

Parameters

host_portu16
Port on the host.
guest_portu16
Port inside the sandbox.

network.port_udp()

Publish a UDP port. The default host bind address is 127.0.0.1.

network.port_bind()

Publish a TCP port on a specific host bind address, such as 0.0.0.0.

Parameters

host_bindIpAddr
Host bind address.
host_portu16
Port on the host.
guest_portu16
Port inside the sandbox.

network.port_udp_bind()

Publish a UDP port on a specific host bind address.

network.dns()

Configure DNS interception. See DnsBuilder.

network.tls()

Configure TLS interception. See TlsBuilder.

network.trust_host_cas()

Whether to ship the host’s trusted root CAs into the guest at boot. Default: false. Opt in when egress HTTPS inside the sandbox needs to work behind corporate MITM proxies (Cloudflare Warp Zero Trust, Zscaler, Netskope, etc.). Those proxies install a gateway CA on the host that’s unknown to the guest’s stock Mozilla bundle.

network.http()

Denial responses are disabled by default. Call deny_response(true) to return 403 Forbidden for supported HTTP requests, including HTTPS on intercepted ports. Optionally set deny_message to customize the body; {host} names the blocked hostname. Setting a message alone does not enable responses. Enabling requires a supporting local runtime; cloud rejects it. See What a denied HTTP request sees. HttpBuilder::build() returns HttpConfig, stored in NetworkConfig.http:
When enabled, None uses the built-in message; Some(String::new()) sends an empty body.

network.strict()

Require hostname-based policy allows to use an inspectable request authority. Default: true. Plain HTTP exposes that authority in Host; HTTPS only exposes it when TLS interception is enabled and not bypassed. Without that visibility, strict mode denies HTTPS that would otherwise be allowed only by a hostname rule.

network.tcp_accept_queue_size()

Set how many not-yet-accepted connections each published TCP port’s host listener queues. Default: 1024. Accepts 1..=i32::MAX; other values record BuildError::InvalidTcpAcceptQueueSize. Connections arriving while the queue is full never reach the sandbox, so raise this when a burst of parallel connections, such as a reverse proxy fanning out one page load, exceeds it. The host kernel caps the effective depth at net.core.somaxconn on Linux (4,096 by default) or kern.ipc.somaxconn on macOS (128 by default). Runtimes that predate the setting are refused with an upgrade-required error rather than silently ignoring it. RestoreBuilder, ForkBuilder, and ForkManyBuilder expose the same tcp_accept_queue_size() for the listeners a child publishes.

network.nat64_prefix()

Add a NAT64 /96 prefix for policy classification. Destinations inside NAT64 prefixes are evaluated against both their IPv6 address and the embedded IPv4 address, so translated private, loopback, link-local, and metadata IPv4 addresses retain their normal policy groups. The well-known 64:ff9b::/96 prefix is configured by default.

Parameters

prefixIpv6Network
NAT64 prefix. Must be an IPv6 /96.

network.max_udp_connections()

Set the runtime UDP relay session limit. Omission is unlimited in single-tenant mode and defaults to 1,024 in multi-tenant mode; zero explicitly selects unlimited. At a finite limit, a new session evicts the least recently active session. Sessions expire after 60 seconds of inactivity. Historical runtime launch contracts reject explicit UDP limits, including zero, with an upgrade-required error.

network.max_tcp_connections()

max_connections remains a deprecated alias for this builder method. The last call sets the TCP limit. Either method can be combined with the UDP limit.
Limit the maximum number of concurrent TCP connections from the sandbox. When omitted, single-tenant mode is unlimited and multi-tenant mode defaults to 1,024. A positive value overrides the default; passing zero explicitly selects unlimited in either mode. Hosting services are responsible for restricting tenant overrides. See deployment profiles for historical TCP limits and defaults. For dedicated snapshot restore, RestoreBuilder::max_tcp_connections and RestoreBuilder::max_udp_connections set the destination limits. RestoreBuilder::max_connections remains a deprecated TCP alias; the last TCP setter call wins.

Parameters

maxusize
Maximum concurrent TCP connections.

network.rate_limiter()

Configure network rate limits. Egress and ingress are independently optional; an omitted direction is unlimited. The limit applies on the next sandbox start.

network.ipv4_pool()

Set the IPv4 pool used to derive per-sandbox /30 guest subnets. Defaults to 172.16.0.0/12. A pool with a prefix longer than /30 records BuildError::InvalidIpv4Pool.

Parameters

poolIpv4Network
IPv4 pool, prefix /30 or shorter.

network.ipv6_pool()

Set the IPv6 pool used to derive per-sandbox /64 guest prefixes. Defaults to fd42:6d73:62::/48. A pool with a prefix longer than /64 records BuildError::InvalidIpv6Pool.

network.interface()

Override the guest interface settings wholesale: MAC, MTU, IPv4/IPv6 addresses, and the derivation pools. A low-level escape hatch. For the common case of changing only the address pools, prefer ipv4_pool() and ipv6_pool(), which validate the prefix. Unset fields fall back to values derived deterministically from the sandbox slot. See InterfaceOverrides.

Parameters

Guest interface overrides.

network.enabled()

Enable or disable networking. Default: true. To fully turn networking off, prefer SandboxBuilder::disable_network(), which also sets the policy to NetworkPolicy::none().

network.secret_violation_action()

Set the sandbox-wide blocking action. Passthrough hosts are configured per secret with allow_placeholder_for().

network.secret()

Add a secret via a closure builder. Mirrors SandboxBuilder::secret(). See SecretBuilder for the full API. A companion secret_env(env_var, value, placeholder, allowed_host) shorthand and secret_entry(SecretEntry) are also available on NetworkBuilder.

Parameters

Configure the secret.

DnsBuilder

Builder for DNS interception, used in NetworkBuilder::dns(|d| d...). Owns rebind protection, nameserver pinning, and the per-query timeout. Every setter returns Self.

dns.nameservers()

Set the upstream nameservers to forward DNS queries to. Replaces any previously-set nameservers. When empty, the interceptor falls back to the host’s /etc/resolv.conf (or, on macOS, the SystemConfiguration dynamic store). Each element converts into Nameserver: a SocketAddr, an IpAddr, or a parsed string via "dns.google:53".parse::<Nameserver>()?.

Parameters

nameserversIntoIterator<Item = Into<Nameserver>>
Upstream resolvers.

dns.query_timeout_ms()

Set the per-DNS-query timeout in milliseconds. Default: 5000.

dns.rebind_protection()

When enabled, the interceptor blocks DNS responses that resolve to private IP addresses, preventing DNS rebinding attacks. Default: true.

TlsBuilder

Builder for TLS interception, used in NetworkBuilder::tls(|t| t...). Creating it enables interception. Every setter returns Self.

tls.bypass()

Skip TLS interception for hosts matching this glob (e.g. "*.internal.corp"). Use for domains with certificate pinning. Can be called multiple times.

Parameters

patternimpl Into<String>
Host glob. Supports exact match and *.suffix wildcards.

tls.intercepted_ports()

TCP ports where TLS interception is active. Default: [443].

tls.verify_upstream()

Whether the proxy verifies upstream server certificates. Default: true. Set to false only for self-signed servers.

tls.block_quic()

Block QUIC/HTTP3 on intercepted ports, forcing TCP/TLS fallback. Default: true.

tls.intercept_ca_cert()

PEM file used as the intercepting CA’s certificate. Pair with intercept_ca_key() to provide a stable CA across sandbox restarts. If unset, a CA is auto-generated and persisted.

tls.intercept_ca_key()

PEM file used as the intercepting CA’s private key.

tls.upstream_ca_cert()

PEM file with extra root CAs the proxy should trust when verifying every upstream server. Useful for self-signed or private upstream CAs. Can be called multiple times.

tls.upstream_ca_cert_for()

PEM file with extra root CAs the proxy should trust only when the upstream SNI matches pattern. Pattern syntax matches bypass(): exact hosts and *.suffix wildcards are supported.

tls.verify_upstream_for()

Whether the proxy verifies upstream server certificates only when the upstream SNI matches pattern. Pattern syntax matches bypass(): exact hosts and *.suffix wildcards are supported. Setting verify to false is the proxy-side equivalent of curl -k for matching hosts; TLS interception still runs.

NetworkRateLimiterBuilder

Groups local rate limits by traffic direction. Supplied to NetworkBuilder::rate_limiter().

.egress()

Configure the guest-to-runtime direction.

.ingress()

Configure the runtime-to-guest direction.

RateLimiterBuilder

Builder for one direction’s rate limiter, supplied to NetworkRateLimiterBuilder::egress() or ingress(). A limiter caps bandwidth (bytes) and packet rate (frames) independently; leaving a bucket unset leaves that dimension unlimited. Buckets start full plus their one-time burst and refill continuously. Every setter returns Self. Validation runs at NetworkBuilder::build(). Each of these surfaces as BuildError: a limiter with neither bucket, a zero bucket size or refill interval, a burst without its bucket, or a refill interval that does not fit in u64 milliseconds.

.bandwidth()

Cap bandwidth at size bytes per refill_time. Size accepts a bare u64 byte count or the unit helpers from microsandbox::size::SizeExt (1.mib(), 512.kib()).

Parameters

sizeimpl Into<Bytes>
Bucket capacity in bytes.
refill_timeDuration
Time to refill the full bucket.

.bandwidth_burst()

Grant a one-time startup burst of extra bytes on top of the bandwidth bucket. The burst is spent before the regular budget and never refills. Requires bandwidth().

.ops()

Cap packet rate at count frames per refill_time.

.ops_burst()

Grant a one-time startup burst of extra frames on top of the ops bucket. Requires ops().

Rule

Held by NetworkPolicy

A single policy rule. The destination interpretation is direction-dependent: egress destination, or ingress peer/source. ports is always the guest-side port (egress destination port / ingress listening port). Convenience constructors build any-protocol, any-port rules:

Rule::allow_egress()

Allow rule, direction Egress

Rule::deny_egress()

Deny rule, direction Egress

Rule::allow_ingress()

Allow rule, direction Ingress

Rule::deny_ingress()

Deny rule, direction Ingress

Rule::allow_any()

Allow rule, direction Any

Rule::deny_any()

Deny rule, direction Any

Rule::allow_dns()

Allow plain DNS (UDP/53 + TCP/53) to the gateway forwarder (Group::Host); the one-liner for opening DNS under deny-by-default. See DNS as egress.

Rule::deny_dns()

Deny plain DNS (UDP/53 + TCP/53) to the gateway forwarder; place before profile-generated rules to override automatic DNS.

PortRange

Held by Rule · added by port() · port_range()

An inclusive port range.

PortRange::single()

Match a single port

PortRange::range()

Match an inclusive range

PortRange::contains()

Whether port falls within the range

DomainName

Held by Destination::Domain / DomainSuffix

A validated, canonical DNS name.

name.as_str()

Borrow the canonical string form

name.try_into_suffix()

Validate for use as a DomainSuffix; single-label names (e.g. com) are rejected

Types

NetworkProfile

Composable high-level access category accepted by NetworkPolicy::from_profiles().

Action

Used by Rule · NetworkPolicy · default_egress()

Direction

Used by Rule

Destination

Held by Rule · committed by RuleDestinationBuilder

DestinationGroup

Held by Destination · committed by RuleBuilder group adders

Groups are disjoint with one carve-out: Metadata takes precedence over LinkLocal for 169.254.169.254, and Host over Private when the gateway IPs sit in CGN/ULA ranges.

Protocol

Held by Rule · set by RuleBuilder protocol setters

ICMP protocols are egress-only. A rule with direction Ingress or Any carrying an ICMP protocol fails build with BuildError::IngressDoesNotSupportIcmp.

Nameserver

Used by nameservers()

An upstream DNS server, either a literal address or a hostname resolved at interceptor startup via the host’s OS resolver. Serializes as a single string. Construct via From<SocketAddr>, From<IpAddr>, or str::parse (errors with ParseNameserverError). Accepted parse forms: 1.1.1.1, 1.1.1.1:5353, 2606:4700:4700::1111, [2606:4700:4700::1111]:53, dns.google, dns.google:53. A bare IP or hostname defaults to port 53.

InterfaceOverrides

Used by interface()

Per-sandbox guest interface overrides. Every field is optional; an omitted field is derived deterministically from the sandbox slot. Most callers only touch the pools via ipv4_pool() / ipv6_pool() rather than constructing this directly.

NetworkRateLimiterConfig

Built by NetworkRateLimiterBuilder · used by rate_limiter()

Network rate limits grouped by direction. An omitted direction is unlimited.

RateLimiterConfig

Built by RateLimiterBuilder · held by NetworkRateLimiterConfig

Rate limiter for one traffic direction. A missing bucket leaves that dimension unlimited.

TokenBucketConfig

Held by RateLimiterConfig

One token bucket of a rate limiter. The bucket starts full and refills continuously at size tokens per refill_time_ms; the one-time burst is spent before the regular budget and never refills.

BuildError

Returned by NetworkPolicyBuilder::build() · wrapped by NetworkBuilder

Errors surfaced by the builders’ build() methods. The same enum covers NetworkPolicy::builder(), DnsBuilder, and NetworkBuilder; the network and DNS builders accumulate lazily, so the first failure surfaces from the outermost build() in the chain. Inside SandboxBuilder::build(), BuildError is wrapped as MicrosandboxError::NetworkBuilder(BuildError).

SecretViolationAction

Used by secret_violation_action()

Action taken when a secret placeholder is sent to a disallowed host. Also documented on the Secrets page, where it pairs with SecretBuilder.