Skip to main content
Configure sandbox networking. See Networking for usage and policy concepts.

NetworkPolicy

Built by NetworkPolicy::builder() · used by policy()

Ordered rules with per-direction defaults.

NetworkPolicy::default_egress

Action Action when no egress-applicable rule matches

NetworkPolicy::default_ingress

Action Action when no ingress-applicable rule matches

NetworkPolicy::rules

Vec<Rule> Ordered rules; first match wins per direction

NetworkPolicy::builder()

Start the fluent NetworkPolicyBuilder. The primary construction path: string inputs (.ip, .cidr, .domain, .domain_suffix) are stored raw and parsed at build(), so the chain stays clean and the first parse or validation failure surfaces as BuildError.

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()

Per-direction override for the egress default action.

Parameters

actionAction
Default action for egress.

policy.default_ingress()

Per-direction override for the ingress default action.

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, validates the direction-set and ICMP-egress-only invariants, and emits a tracing::warn! for each shadowed rule pair (a rule fully covered by an earlier one in the same direction; only Ip / Cidr / Group destinations are checked). 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 trap.
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 excluded; opt in via allow_meta() separately.

rule.deny_local()

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

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.max_connections()

Limit the maximum number of concurrent network connections from the sandbox. Default: 256.

Parameters

maxusize
Maximum concurrent 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.on_secret_violation()

Set the sandbox-wide action taken when a secret placeholder is detected in traffic to a host not in the secret’s allow list. See ViolationActionBuilder. Passthrough hosts receive the placeholder unchanged. They do not receive real secret values.

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, DNS responses that resolve to private IP addresses are blocked, 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.

ViolationActionBuilder

Builder for secret-violation behavior.

violation.block()

Block the request silently.

violation.block_and_log()

Block the request and emit a warning log on the host. This is the ViolationAction default.

violation.block_and_terminate()

Block the request and terminate the entire sandbox.

violation.passthrough_host()

Allow an exact host to receive secret placeholders unchanged (no substitution).

Parameters

hostimpl Into<String>
Exact host.

violation.passthrough_host_pattern()

Allow hosts matching a wildcard pattern (e.g. *.example.com) to receive placeholders unchanged.

violation.passthrough_all_hosts()

Allow any host to receive placeholders unchanged. Takes effect only when i_understand_the_risk is true.

Parameters

i_understand_the_riskbool
Must be true to take effect.

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(): 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 surfaces as BuildError.

.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).

Rule::direction

Direction Which evaluator considers this rule

Rule::destination

Destination Target filter

Rule::protocols

Vec<Protocol> Set semantics; empty = any protocol

Rule::ports

Vec<PortRange> Set semantics; empty = any port

Rule::action

Action What to do on match 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::start

u16 Start port (inclusive)

PortRange::end

u16 End port (inclusive)

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).

ViolationAction

Built by ViolationActionBuilder · used by on_secret_violation()

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