Back to Microsandbox

Networking

docs/sdk/go/networking.mdx

0.6.721.0 KB
Original Source

Configure a sandbox's network stack: a first-match-wins egress/ingress policy, published ports, DNS interception, TLS interception, and secret-violation handling. See Networking for the conceptual overview and TLS Interception for proxy details.

The Go SDK exposes networking as a single NetworkConfig struct passed to WithNetwork. Common shapes come from the NetworkPolicy factory; custom firewalls are built by populating NetworkConfig.Rules directly.

<p className="msb-label" id="typical-flow">Typical flow</p>
go
import m "github.com/superradcompany/microsandbox/sdk/go"

// Public internet profile
sb, err := m.CreateSandbox(ctx, "worker",
    m.WithImage("alpine"),
    m.WithNetwork(m.NetworkPolicy.FromProfiles(m.NetworkProfilePublic)),
)

// Or a custom first-match-wins firewall
sb, err = m.CreateSandbox(ctx, "ci-runner",
    m.WithImage("python:3.12"),
    m.WithNetwork(&m.NetworkConfig{
        DefaultEgress:  m.PolicyActionDeny,
        DefaultIngress: m.PolicyActionAllow,
        Rules: []m.PolicyRule{
            {
                Action:      m.PolicyActionAllow,
                Direction:   m.PolicyDirectionEgress,
                Destination: "api.example.com",
                Protocol:    m.PolicyProtocolTCP,
                Port:        "443",
            },
        },
    }),
)

Functions

<span className="msb-recv">m.</span><span className="msb-hn">WithNetwork()</span>

go
func WithNetwork(net *NetworkConfig) SandboxOption
<Accordion title="Example">
go
sb, err := m.CreateSandbox(ctx, "worker",
    m.WithImage("alpine"),
    m.WithNetwork(m.NetworkPolicy.FromProfiles(m.NetworkProfilePublic)),
)
</Accordion>

Set the network configuration for the sandbox. Pass a profile policy from the NetworkPolicy factory, or a custom NetworkConfig value with your own rules, DNS, TLS, and port settings.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>net</code><a className="msb-type" href="#networkconfig">*NetworkConfig</a></div> <div className="msb-param-desc">Network stack configuration.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">SandboxOption</span></div> <div className="msb-param-desc">Option to pass to <a className="msb-type" href="/sdk/go/sandbox#createsandbox">CreateSandbox</a>.</div> </div> </div>

<span className="msb-recv">m.</span><span className="msb-hn">WithPorts()</span>

go
func WithPorts(ports map[uint16]uint16) SandboxOption
<Accordion title="Example">
go
sb, err := m.CreateSandbox(ctx, "api",
    m.WithImage("python:3.12"),
    m.WithPorts(map[uint16]uint16{8080: 8080}),
)
</Accordion>

Make TCP services running in the sandbox reachable on localhost ports on the host. Each map entry exposes the guest port (value) on the host port (key), bound to 127.0.0.1. Called multiple times, the maps merge.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>ports</code><span className="msb-type">map[uint16]uint16</span></div> <div className="msb-param-desc">Host port to guest port (TCP).</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">SandboxOption</span></div> <div className="msb-param-desc">Option to pass to <a className="msb-type" href="/sdk/go/sandbox#createsandbox">CreateSandbox</a>.</div> </div> </div>

<span className="msb-recv">m.</span><span className="msb-hn">WithPortsUDP()</span>

go
func WithPortsUDP(ports map[uint16]uint16) SandboxOption
<Accordion title="Example">
go
sb, err := m.CreateSandbox(ctx, "dns",
    m.WithImage("alpine"),
    m.WithPortsUDP(map[uint16]uint16{5353: 53}),
)
</Accordion>

Make UDP services running in the sandbox reachable on localhost ports on the host. Each map entry exposes the guest port (value) on the host port (key), bound to 127.0.0.1. Called multiple times, the maps merge.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>ports</code><span className="msb-type">map[uint16]uint16</span></div> <div className="msb-param-desc">Host port to guest port (UDP).</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">SandboxOption</span></div> <div className="msb-param-desc">Option to pass to <a className="msb-type" href="/sdk/go/sandbox#createsandbox">CreateSandbox</a>.</div> </div> </div>

<span className="msb-recv">m.</span><span className="msb-hn">WithPortBindings()</span>

go
func WithPortBindings(bindings ...PortBinding) SandboxOption
<Accordion title="Example">
go
sb, err := m.CreateSandbox(ctx, "api",
    m.WithImage("python:3.12"),
    m.WithPortBindings(
        m.PortBinding{Bind: "0.0.0.0", HostPort: 8001, GuestPort: 8001},
        m.PortBinding{Bind: "127.0.0.1", HostPort: 5353, GuestPort: 53, Protocol: m.PortProtocolUDP},
    ),
)
</Accordion>

Make services running in the sandbox reachable on explicit host addresses and ports. Use this when the default 127.0.0.1 bind is too restrictive, for example to expose a port on 0.0.0.0. Accepts one or more PortBinding values.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>bindings</code><a className="msb-type" href="#portbinding">...PortBinding</a></div> <div className="msb-param-desc">Explicit bind address, host port, guest port, and protocol.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">SandboxOption</span></div> <div className="msb-param-desc">Option to pass to <a className="msb-type" href="/sdk/go/sandbox#createsandbox">CreateSandbox</a>.</div> </div> </div>

NetworkPolicy

Factory namespace returning high-level *NetworkConfig values. Access through the package-level NetworkPolicy value.

<span className="msb-recv">NetworkPolicy.</span><span className="msb-hn">FromProfiles()</span>

go
func (networkPolicyFactory) FromProfiles(profiles ...NetworkProfile) *NetworkConfig
<Accordion title="Example">
go
m.WithNetwork(m.NetworkPolicy.FromProfiles(
    m.NetworkProfilePublic,
    m.NetworkProfilePrivate,
))
</Accordion>

Build a deny-by-default policy from NetworkProfilePublic, NetworkProfilePrivate, and NetworkProfileHost. Duplicate profiles are ignored, rules use canonical order, and each non-empty set receives one gateway DNS rule. An empty profile set permits no egress and adds no DNS; ingress defaults to allow.

FromProfiles panics if passed a value other than the three package-defined NetworkProfile constants.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#networkconfig">*NetworkConfig</a></div> <div className="msb-param-desc">Config containing canonical profile and DNS rules.</div> </div> </div>

When profile names come from JSON, configuration, environment variables, or other runtime input, use the checked variant instead:

go
network, err := m.NetworkPolicy.FromProfilesChecked(profiles...)
if err != nil {
    return err
}

<span className="msb-recv">NetworkPolicy.</span><span className="msb-hn">FromProfilesChecked()</span>

go
func (networkPolicyFactory) FromProfilesChecked(profiles ...NetworkProfile) (*NetworkConfig, error)

Builds the same canonical deny-by-default policy as FromProfiles, but returns an error instead of panicking when a profile is unknown. Use this method for values derived from runtime input.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#networkconfig">*NetworkConfig</a></div> <div className="msb-param-desc">Config containing canonical profile and DNS rules.</div> </div> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">error</span></div> <div className="msb-param-desc">Non-nil when any requested profile is unknown.</div> </div> </div>

<span className="msb-recv">NetworkPolicy.</span><span className="msb-hn">None()</span>

go
func (networkPolicyFactory) None() *NetworkConfig
<Accordion title="Example">
go
m.WithNetwork(m.NetworkPolicy.None())
</Accordion>

Block all network traffic in both directions. The network interface remains present; Exec and FS still work because they use the host-guest channel.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#networkconfig">*NetworkConfig</a></div> <div className="msb-param-desc">Config with deny defaults in both directions.</div> </div> </div>

<span className="msb-recv">NetworkPolicy.</span><span className="msb-hn">AllowAll()</span>

go
func (networkPolicyFactory) AllowAll() *NetworkConfig
<Accordion title="Example">
go
m.WithNetwork(m.NetworkPolicy.AllowAll())
</Accordion>

Permit all network traffic, including private addresses and the host machine.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#networkconfig">*NetworkConfig</a></div> <div className="msb-param-desc">Config with allow defaults in both directions.</div> </div> </div>

Rule

The package-level Rule factory provides semantic low-level rules. Rule.AllowDNS() returns a PolicyRule allowing gateway UDP/53 and TCP/53; Rule.DenyDNS() returns its deny counterpart. Put Rule.DenyDNS() before profile-generated rules when you need to override automatic DNS access.

go
network := m.NetworkPolicy.FromProfiles(m.NetworkProfilePublic)
network.Rules = append([]m.PolicyRule{m.Rule.DenyDNS()}, network.Rules...)

Custom rules

Build a custom firewall by populating NetworkConfig.Rules. Rules are evaluated first-match-wins per direction; DefaultEgress and DefaultIngress set the fall-through action. A broad rule placed before a narrow one swallows it, so put specific rules first.

go
sb, err := m.CreateSandbox(ctx, "ci-runner",
    m.WithImage("python:3.12"),
    m.WithNetwork(&m.NetworkConfig{
        DefaultEgress:  m.PolicyActionDeny,
        DefaultIngress: m.PolicyActionAllow,
        Rules: []m.PolicyRule{
            {Action: m.PolicyActionDeny, Destination: "10.0.0.5"},      // specific first
            {Action: m.PolicyActionAllow, Destination: "10.0.0.0/8"},   // broad fallthrough
            {
                Action:      m.PolicyActionAllow,
                Direction:   m.PolicyDirectionEgress,
                Destination: ".internal",
                Protocols:   []m.PolicyProtocol{m.PolicyProtocolTCP},
                Ports:       []string{"8000-9000"},
            },
        },
    }),
)

Types

NetworkConfig

<p className="msb-backref">Used by <a href="#m-withnetwork">WithNetwork()</a> · returned by <a href="#networkpolicy">NetworkPolicy</a></p>

The full network stack configuration passed via WithNetwork.

FieldTypeDescription
Rules[]PolicyRuleOrdered custom rules (first match wins)
DefaultEgressPolicyActionFall-through action for outbound when no rule matches. Defaults to "deny"
DefaultIngressPolicyActionFall-through action for inbound when no rule matches. Defaults to "allow"
DenyDomains[]stringExact domain names to refuse DNS resolution for
DenyDomainSuffixes[]stringDomain suffixes (e.g. .ads) to block, including the apex and any subdomain
DNS*DNSConfigIn-VM DNS proxy settings
DNSRebindProtection*boolLegacy convenience for DNS.RebindProtection. When DNS is also set, the nested value wins
TLS*TLSConfigTransparent TLS interception proxy settings
Portsmap[uint16]uint16Host to guest TCP port mappings bound to 127.0.0.1
PortBindings[]PortBindingHost to guest mappings with explicit bind addresses
IPv4PoolstringPool used to derive per-sandbox /30 guest subnets. Defaults to 172.16.0.0/12
IPv6PoolstringPool used to derive per-sandbox /64 guest prefixes. Defaults to fd42:6d73:62::/48
MaxConnections*uintCap on concurrent network connections from the sandbox
OnSecretViolationViolationActionSandbox-wide action when a secret is sent to a disallowed host. Per-secret overrides via SecretEntry.OnViolation
TrustHostCAs*boolShip the host's extra CA bundles into the guest. Opt-in for corporate MITM proxies whose gateway CA is unknown to the guest's stock bundle

PolicyRule

<p className="msb-backref">Used by <a href="#networkconfig">NetworkConfig.Rules</a></p>

A single firewall rule. Ingress rules carrying ICMP protocols are rejected at sandbox creation, since the host has no inbound ICMP path; use PolicyDirectionEgress for ICMP.

FieldTypeDescription
ActionPolicyActionallow or deny
DirectionPolicyDirectionDirection this rule considers. PolicyDirectionAny matches in either
DestinationstringTarget filter: a destination group, domain, domain suffix (prefixed with .), CIDR (10.0.0.0/8), exact IP, or "*"
ProtocolPolicyProtocolLegacy single-protocol field. The empty string means any. Prefer Protocols when matching multiple
Protocols[]PolicyProtocolProtocol set. Empty means any
PortstringSingle port ("443") or range ("8000-9000")
Ports[]stringSeveral port values at once

DNSConfig

<p className="msb-backref">Used by <a href="#networkconfig">NetworkConfig.DNS</a></p>

In-VM DNS proxy configuration.

FieldTypeDescription
RebindProtection*boolBlock DNS responses resolving to private IPs. Defaults to true when unset
Nameservers[]stringUpstream resolvers (e.g. "1.1.1.1:53"). Replaces /etc/resolv.conf when non-empty
QueryTimeoutMs*uint64Per-DNS-query timeout in milliseconds

TLSConfig

<p className="msb-backref">Used by <a href="#networkconfig">NetworkConfig.TLS</a></p>

Transparent HTTPS inspection proxy configuration.

FieldTypeDescription
Bypass[]stringDomain patterns (supports *.suffix) to skip MITM. Use for domains with certificate pinning
VerifyUpstream*boolVerify upstream server certificates. Defaults to true. Set false only for self-signed servers
InterceptedPorts[]uint16TCP ports where TLS is intercepted. Defaults to [443]
BlockQUIC*boolBlock QUIC on intercepted ports to force TLS fallback
CACertstringPath to a custom interception CA certificate PEM file
CAKeystringPath to a custom interception CA private key PEM file
UpstreamCACerts[]stringPaths to additional CA bundles trusted for every upstream host
ScopedUpstreamCACerts[]ScopedUpstreamCACertHost-pattern-scoped CA bundles trusted only for matching upstream hosts
ScopedVerifyUpstream[]ScopedVerifyUpstreamHost-pattern-scoped upstream certificate verification overrides
go
sb, err := m.CreateSandbox(ctx, "inspect",
    m.WithImage("python:3.12"),
    m.WithNetwork(&m.NetworkConfig{
        TLS: &m.TLSConfig{
            Bypass:           []string{"*.googleapis.com"},
            InterceptedPorts: []uint16{443},
        },
    }),
)

ScopedUpstreamCACert

<p className="msb-backref">Used by <a href="#tlsconfig">TLSConfig.ScopedUpstreamCACerts</a></p>

Host-scoped upstream CA bundle configuration.

FieldTypeDescription
PatternstringExact host or *.suffix wildcard
PathstringCA bundle path trusted for matching upstream hosts

ScopedVerifyUpstream

<p className="msb-backref">Used by <a href="#tlsconfig">TLSConfig.ScopedVerifyUpstream</a></p>

Host-scoped upstream certificate verification override.

FieldTypeDescription
PatternstringExact host or *.suffix wildcard
VerifyboolWhether to verify certificates for matching upstream hosts

PortBinding

<p className="msb-backref">Used by <a href="#m-withportbindings">WithPortBindings()</a> · <a href="#networkconfig">NetworkConfig.PortBindings</a></p>

A host-to-guest port mapping with an explicit host bind address. Protocol defaults to TCP when empty. Use Bind: "0.0.0.0" to expose the published port on all IPv4 interfaces.

FieldTypeDescription
BindstringHost IP address to bind, such as 127.0.0.1, 0.0.0.0, or ::
HostPortuint16Port on the host
GuestPortuint16Port inside the sandbox
ProtocolPortProtocolPortProtocolTCP or PortProtocolUDP. Empty defaults to TCP

PortProtocol

<p className="msb-backref">Used by <a href="#portbinding">PortBinding.Protocol</a></p>

Identifies the protocol for an exposed sandbox service.

ConstantValueDescription
PortProtocolTCP"tcp"TCP port mapping
PortProtocolUDP"udp"UDP port mapping

PolicyAction

<p className="msb-backref">Used by <a href="#policyrule">PolicyRule.Action</a> · <a href="#networkconfig">NetworkConfig.DefaultEgress</a></p>

The action half of a PolicyRule.

ConstantValueDescription
PolicyActionAllow"allow"Permit the traffic
PolicyActionDeny"deny"Drop the traffic silently

PolicyDirection

<p className="msb-backref">Used by <a href="#policyrule">PolicyRule.Direction</a></p>

The direction half of a PolicyRule. The Go SDK follows the Python naming (egress/ingress); the wire format carries these values.

ConstantValueDescription
PolicyDirectionEgress"egress"Traffic leaving the sandbox
PolicyDirectionIngress"ingress"Traffic entering the sandbox
PolicyDirectionAny"any"Rule applies in either direction

PolicyProtocol

<p className="msb-backref">Used by <a href="#policyrule">PolicyRule.Protocol</a> · <a href="#policyrule">PolicyRule.Protocols</a></p>

The protocol half of a PolicyRule.

ConstantValueDescription
PolicyProtocolTCP"tcp"TCP traffic
PolicyProtocolUDP"udp"UDP traffic
PolicyProtocolICMPv4"icmpv4"ICMPv4 traffic (egress only)
PolicyProtocolICMPv6"icmpv6"ICMPv6 traffic (egress only)

NetworkProfile

Composable profile names accepted by NetworkPolicy.FromProfiles().

ConstantValueDescription
NetworkProfilePublic"public"Public internet addresses
NetworkProfilePrivate"private"Private/LAN ranges
NetworkProfileHost"host"Sandbox host gateway addresses

Destination groups

<p className="msb-backref">Used by <a href="#policyrule">PolicyRule.Destination</a></p>

The Destination field on PolicyRule accepts these well-known group names alongside literal CIDRs and domains. A domain prefixed with . becomes a suffix match: .example.com matches api.example.com but not example.com.

ValueDescription
"public"Every address not in any other group
"private"Private/RFC 1918 addresses + ULA + CGN (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 100.64.0.0/10, fc00::/7)
"loopback"Loopback addresses (127.0.0.0/8, ::1); the guest's own loopback, not the host. See Reaching the host
"link-local"Link-local addresses (169.254.0.0/16, fe80::/10) excluding metadata
"metadata"Cloud metadata endpoints (169.254.169.254)
"multicast"Multicast addresses (224.0.0.0/4, ff00::/8)
"host"The host machine, reached via host.microsandbox.internal. The right group for "let the sandbox reach my host's localhost", not "loopback"