> ## Documentation Index
> Fetch the complete documentation index at: https://docs.microsandbox.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> Control network access and isolation

All sandbox traffic flows through a host-controlled networking stack. From inside the VM it looks like a normal network interface; from the host side, every packet is checked against policy before it leaves.

## Defaults

By default, sandboxes can reach the public internet but cannot reach private networks, loopback, link-local addresses, or cloud metadata endpoints. Inbound traffic is only reachable through published ports.

To turn networking off entirely:

<CodeGroup>
  ```rust Rust theme={null}
  let sb = Sandbox::builder("isolated")
      .image("python")
      .network(|n| n.enabled(false))
      .create()
      .await?;
  ```

  ```typescript TypeScript theme={null}
  await using sb = await Sandbox.builder("isolated")
      .image("python")
      .disableNetwork()
      .create();
  ```

  ```python Python theme={null}
  from microsandbox import Network, Sandbox

  sb = await Sandbox.create("isolated", image="python", network=Network.none())
  ```

  ```go Go theme={null}
  sb, err := m.CreateSandbox(ctx, "isolated",
      m.WithImage("python"),
      m.WithNetwork(m.NetworkPolicy.None()),
  )
  ```

  ```bash CLI theme={null}
  msb create python --name isolated --no-net
  ```
</CodeGroup>

## Custom policies

A policy has two defaults and an ordered list of rules. The first matching rule wins.

```text theme={null}
default_egress  : allow | deny
default_ingress : allow | deny
rules           : first match wins
```

For example, this creates a deny-by-default sandbox that can make HTTPS requests to the public internet and DNS requests through the host gateway:

<CodeGroup>
  ```rust Rust theme={null}
  let policy = NetworkPolicy::builder()
      .default_deny()
      .egress(|e| e.tcp().port(443).allow_public())
      .egress(|e| e.udp().tcp().port(53).allow_host())
      .build()?;

  let sb = Sandbox::builder("restricted-worker")
      .image("alpine")
      .network(|n| n.policy(policy))
      .create()
      .await?;
  ```

  ```typescript TypeScript theme={null}
  import { NetworkPolicy, Sandbox } from "microsandbox";

  await using sb = await Sandbox.builder("restricted-worker")
      .image("alpine")
      .network((n) => n.policy(
          NetworkPolicy.builder()
              .defaultDeny()
              .egress((e) => e.tcp().port(443).allowPublic())
              .egress((e) => e.udp().tcp().port(53).allowHost())
              .build(),
      ))
      .create();
  ```

  ```python Python theme={null}
  from microsandbox import Network, Sandbox

  sb = await Sandbox.create(
      "restricted-worker",
      image="alpine",
      network={
          "policy": {
              "default_egress": "deny",
              "rules": [
                  {"action": "allow", "direction": "egress", "destination": "public", "protocol": "tcp", "port": "443"},
                  {"action": "allow", "direction": "egress", "destination": "host", "protocol": "udp", "port": "53"},
              ],
          },
      },
  )
  ```

  ```go Go theme={null}
  sb, err := m.CreateSandbox(ctx, "restricted-worker",
      m.WithImage("alpine"),
      m.WithNetwork(&m.NetworkConfig{
          DefaultEgress: m.PolicyActionDeny,
          Rules: []m.PolicyRule{
              {Action: m.PolicyActionAllow, Direction: m.PolicyDirectionEgress, Destination: "public", Protocol: m.PolicyProtocolTCP, Port: "443"},
              {Action: m.PolicyActionAllow, Direction: m.PolicyDirectionEgress, Destination: "host", Protocol: m.PolicyProtocolUDP, Port: "53"},
          },
      }),
  )
  ```

  ```bash CLI theme={null}
  msb create alpine --name restricted-worker \
    --net-default-egress deny \
    --net-rule "allow@public:tcp:443,allow@host:udp:53"
  ```
</CodeGroup>

Rules can target groups like `public`, `private`, and `host`, or specific IPs, CIDRs, domains, and port ranges. See the [CLI reference](/cli/sandbox-commands#network-rule-syntax) or your language's SDK networking reference for exact syntax.

## Port mapping

Publish a guest port when a service inside the sandbox should be reachable from the host. Published ports bind to `127.0.0.1` by default.

<CodeGroup>
  ```rust Rust theme={null}
  let sb = Sandbox::builder("api")
      .image("python")
      .port(8080, 80)
      .create()
      .await?;
  ```

  ```typescript TypeScript theme={null}
  await using sb = await Sandbox.builder("api")
      .image("python")
      .port(8080, 80)
      .create();
  ```

  ```python Python theme={null}
  from microsandbox import PortBinding, Sandbox

  sb = await Sandbox.create("api", image="python", ports=[PortBinding.tcp(8080, 80)])
  ```

  ```go Go theme={null}
  sb, err := m.CreateSandbox(ctx, "api",
      m.WithImage("python"),
      m.WithPorts(map[uint16]uint16{8080: 80}),
  )
  ```

  ```bash CLI theme={null}
  msb create python --name api -p 8080:80
  ```
</CodeGroup>

Use an explicit bind address, such as `0.0.0.0`, only when you intentionally want to listen beyond localhost.

## Reaching the host

From inside the sandbox, `host.microsandbox.internal` resolves to the host machine. The default policy denies host access, so allow the `host` group when a sandbox needs to call a dev server, database, or other local service.

```bash theme={null}
msb create python --name devbox \
  --net-rule "allow@public,allow@host"
```

`loopback` means the sandbox's own `127.0.0.1`, not your laptop's localhost. Use `host` for `host.microsandbox.internal`.

## Next

* [DNS](/networking/dns): domain blocking, pinned nameservers, query timeouts
* [TLS interception](/networking/tls): HTTPS inspection with an auto-generated CA
* [Security model](/networking/security-model): SSRF, rebinding, and metadata protection
