01Documentation
Network
SandboxNetworkPolicy controls outbound traffic for a sandbox.
Use mode as the default fallback, and use egress.trafficRules for explicit ordered allow and deny behavior.
Cloud metadata and host credential endpoints are protected by the platform. An
allow-all policy or explicit allow rule cannot grant access to those destinations.
An active-policy update is acknowledged only after the node applies the new policy and reconciles existing connections. Concurrent updates are serialized against the current policy and runtime version; a delayed retry cannot restore an older policy. Reopening access requires a new TCP connection after revocation.
Policy Shape#
| Field | Description |
|---|---|
mode | Default fallback for unmatched traffic: allow-all or block-all |
egress.trafficRules | Ordered allow/deny rules. First matching rule wins |
egress.protocolRules | Protocol-aware operation controls for allowed traffic. See Protocol Controls |
egress.credentialRules | Destination-scoped outbound auth rules, optionally constrained by HTTP request matchers. See Credential / Egress Auth |
egress.proxy | Customer-managed SOCKS5 route for allowed TCP traffic. See Egress Proxy |
network.credentialBindings | Local bindings used by credentialRules. See Credential / Egress Auth |
The same public SandboxNetworkPolicy shape is used in:
- template
spec.network - sandbox claim
config.network - runtime
GETandPUT/api/v1/sandboxes/{id}/network
Mode And Rule Evaluation#
trafficRulesare evaluated in order.- The first matching rule wins.
- If no rule matches, traffic falls back to
mode.
Use trafficRules for new policies. Legacy allowed* and denied* fields still work, but they are deprecated and should not be mixed with trafficRules.
If a credential rule uses tlsMode: terminate-reoriginate, Sandbox0 exposes the ctld network runtime's MITM CA as SANDBOX0_NETWORK_MITM_CA_FILE and configures procd-managed processes with a combined CA bundle through common TLS environment variables.
Traffic Rule Fields#
| Field | Required | Description |
|---|---|---|
action | Yes | allow or deny |
name | No | Stable identifier for replacement and merge |
domains | No | Domain match list |
cidrs | No | CIDR match list |
ports | No | Port/protocol constraints |
appProtocols | No | Classified application protocols such as http, tls, ssh, dns, redis |
HTTP Request Matchers#
credentialRules[*].httpMatch narrows credential injection for HTTP-family rules after the HTTP request is visible to the ctld network runtime. It can match methods, exact paths, path prefixes, query parameters, and headers.
For HTTPS and gRPC rules, request matching requires tlsMode: terminate-reoriginate so the ctld network runtime can read the request before injecting credentials.
Protocol Rules#
protocolRules run after traffic is allowed. HTTP rules can limit request methods and paths; MCP rules can limit remote MCP tool calls by tool name.
For HTTPS HTTP or MCP rules, set tlsMode: terminate-reoriginate on the protocol rule so the ctld network runtime can inspect request contents.
Get Network Policy#
/api/v1/sandboxes/{id}/network
gopolicy, err := sandbox.GetNetworkPolicy(ctx) if err != nil { log.Fatal(err) } fmt.Printf("mode=%s\n", policy.Mode)
Update Network Policy#
/api/v1/sandboxes/{id}/network
For a running Nomad sandbox, manager records the desired policy against the exact active allocation and asks the node-local ctld runtime to apply it. The new policy becomes visible from GET only after PostgreSQL commits ctld's matching applied-policy token. If manager or the node channel disconnects after the request is recorded, PUT can return 503 while a background controller continues the same idempotent operation; retrying the same PUT is safe. Pause, deletion, hard expiry, or allocation replacement cancels an unacknowledged update instead of publishing policy for the wrong runtime.
Stock gVisor transfers the carrier's IP address into its userspace network stack at startup. Active-policy validation retains the originally registered source address while checking the exact namespace identity and live carrier link. A missing link or conflicting host address prevents acknowledgement; an IP still owned by a live runtime cannot be silently reassigned to another policy.
Before acknowledging a changed or removed policy, ctld closes TCP proxy connections and UDP sessions authorized by the previous runtime or policy version. Clients must reconnect after a policy update, including updates that still permit the same destination. Closing both upstream and downstream sockets prevents idle relays from surviving sandbox termination; an IP reused by another runtime cannot inherit the previous runtime's proxy session.
Credential-binding changes use the same Nomad desired/apply/ack path. Manager keeps effective bindings outside the sanitized sandbox config, includes their source-version-independent digest in the node policy, and stages referenced sources without changing the current runtime projection. Only a matching ctld acknowledgement atomically publishes the request policy, current bindings, claim digest, and runtime-slot policy digest. A source rotation that races the update wins either before publication or advances the newly published bindings afterward. Cancellation removes the staged source pins, while deletion removes the current bindings before the durable claim is marked cleaned.
Allow Only GitHub HTTPS#
go_, err = sandbox.UpdateNetworkPolicy(ctx, apispec.SandboxNetworkPolicy{ Mode: apispec.SandboxNetworkPolicyModeBlockAll, Egress: apispec.NewOptNetworkEgressPolicy(apispec.NetworkEgressPolicy{ TrafficRules: []apispec.TrafficRule{ { Name: apispec.NewOptString("allow-github"), Action: apispec.TrafficRuleActionAllow, Domains: []string{"github.com", "api.github.com"}, Ports: []apispec.PortSpec{ { Port: 443, Protocol: apispec.NewOptString("tcp"), }, }, }, }, }), }) if err != nil { log.Fatal(err) }
Legacy Compatibility#
egress.allowedDomains, allowedCidrs, allowedPorts, deniedDomains, deniedCidrs, and deniedPorts are still accepted for compatibility:
- In
block-all, onlyallowed*fields are enforced. - In
allow-all, onlydenied*fields are enforced.
Prefer trafficRules for all new policies.