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

# Network Controls

> Cut off a sandbox's internet, or allow only specific IPv4 destinations, using the internet_settings policy on Firecracker and QEMU sandboxes.

Use `internet_settings` when a sandbox should run with no outbound access, or should only reach a short list of IPv4 destinations. Celesto enforces the policy on both Firecracker and QEMU, validates it before allocating any resources, and preserves it across the sandbox's lifetime.

## Choose a mode

| Mode         | Behavior                                                            |
| ------------ | ------------------------------------------------------------------- |
| `open`       | Full outbound internet access. This is the default.                 |
| `off`        | Blocks sandbox-initiated external TCP, UDP, and DNS traffic.        |
| `restricted` | Allows only the IPv4 addresses or ranges listed in `allowed_cidrs`. |

Copy-paste a policy declaration:

```python theme={null}
from celesto import InternetSettings

policy = InternetSettings(
    mode="restricted",
    allowed_cidrs=["203.0.113.10", "198.51.100.0/24"],
)
```

You can also pass a plain dict as `internet_settings={"mode": "off"}` or `{"mode": "restricted", "allowed_cidrs": [...]}` on `Celesto(...)`, `Celesto.from_image(...)`, or `VMConfig(...)`.

## Platform coverage

| Backend / network                        | macOS         | Linux                       | Requirements             |
| ---------------------------------------- | ------------- | --------------------------- | ------------------------ |
| Firecracker (default private networking) | Not supported | `open`, `off`, `restricted` | `comm_channel="vsock"`   |
| QEMU `slirp` (default)                   | `open`, `off` | `open`, `off`               | None                     |
| QEMU `tap` (explicit)                    | Not supported | `open`, `off`, `restricted` | Existing Linux TAP setup |

These controls apply to Linux guests. Windows and macOS guests are not included. Celesto never switches a QEMU sandbox to TAP automatically; opt in with `network="tap"` on `Celesto.from_image` or `qemu_network="tap"` on `VMConfig`.

## Turn outbound access off

QEMU can block outbound access on both macOS and Linux while keeping local application access and shared folders available:

```python theme={null}
from celesto import Celesto

with Celesto(
    backend="qemu",
    internet_settings={"mode": "off"},
) as vm:
    print(vm.run("echo hello").stdout)
```

QEMU `slirp` uses QEMU's built-in restriction and disables IPv6. Launch-time port forwards continue to work.

On Linux, Firecracker also supports off mode when commands and files use the direct `vsock` connection:

```python theme={null}
with Celesto(
    backend="firecracker",
    comm_channel="vsock",
    internet_settings={"mode": "off"},
) as vm:
    print(vm.run("echo hello").stdout)
```

Firecracker `off` mode blocks all guest-initiated IP traffic, including DNS and connections to your machine. Command output and explicit file downloads still leave the sandbox through the direct `vsock` connection.

## Allow specific IPv4 destinations

Use `restricted` with the addresses or network ranges the task needs. This mode requires Firecracker on Linux with `comm_channel="vsock"`, or explicit QEMU TAP networking on Linux.

With a prepared `BootImage` named `image`:

```python theme={null}
from celesto import Celesto

vm = Celesto.from_image(
    image,
    backend="qemu",
    network="tap",
    internet_settings={
        "mode": "restricted",
        "allowed_cidrs": ["203.0.113.10/32"],
    },
)
```

Replace `203.0.113.10` with your application's destination. `/32` allows one address; a range such as `10.20.0.0/24` allows multiple addresses. Bare IPv4 addresses are accepted too. Overlapping ranges are combined.

For direct `VMConfig` construction, use `backend="qemu"`, `qemu_network="tap"`, and the same `internet_settings`. See [Network configuration](/smolvm/concepts/networking) for the required Linux TAP setup.

Only listed destinations can receive new outbound connections, on any port or protocol. IPv6 and sandbox-initiated connections to your machine are blocked. Sandbox and link-local ranges (including the common cloud metadata address `169.254.169.254`) cannot be allowed. DNS is not added automatically, so either connect by IP address or explicitly include the resolver's address; allowing a resolver permits other traffic to that same address too.

In off and restricted TAP modes, the sandbox can reply to IPv4 TCP connections initiated by your machine. This keeps applications, SSH, and shared-folder setup usable without allowing new outbound connections.

## Validate before allocating resources

Celesto validates a policy before it prepares images, boots the VM, or reserves host resources. Invalid settings raise `celesto.ValidationError` from public `Celesto` methods, and Pydantic's `ValidationError` from direct `InternetSettings` or `VMConfig` construction:

```python theme={null}
from celesto import Celesto, ValidationError

try:
    Celesto(internet_settings={"mode": "restricted"})
except ValidationError as error:
    print(error)  # restricted requires allowed_cidrs
    print(error.details.get("errors", []))
```

The validator rejects:

* Unknown fields (for example, misspelling `mode` cannot silently enable internet access).
* Unsupported options such as `allowed_ports` or non-wildcard `allowed_http_methods`.
* `restricted` without any `allowed_cidrs`, or `allowed_cidrs` without `mode="restricted"`.
* IPv6, sandbox, and link-local ranges.
* Combining `mode` with `allowed_domains`.
* Unsupported backend, OS, or network combinations (for example, QEMU `restricted` on macOS, or `off`/`restricted` with bridged networking).

Unsupported combinations fail with an explanatory message that names the recovery step, so the sandbox never starts in a partially-enforced state.

## Interactions with other features

* **Shared folders and exposed ports.** Firecracker `off` and `restricted` do not support shared folders or exposed ports; omit `mounts`, `port_forwards`, and `workspace_mounts`. QEMU keeps both available: `slirp` retains configured launch-time `port_forwards` across restart and snapshot restore, and TAP applications use their guest IP or `expose_local()` instead.
* **SSH command channel.** Firecracker `off` and `restricted` require `comm_channel="vsock"`. SSH cannot reach a sandbox with no outbound path back to your machine.
* **Bridged networking.** Bridge mode ignores private-network policy; `internet_settings` other than `open` is rejected.
* **Legacy `allowed_domains`.** Existing callers can still pass `allowed_domains` on Firecracker private networking or QEMU TAP. Celesto resolves each name to IPv4 addresses at setup and allows traffic to those addresses on any port. Do not combine `allowed_domains` with `mode`; HTTP-method restrictions are rejected.

## Reach an application inside the sandbox

Network restrictions do not prevent your machine from reaching an application inside a QEMU sandbox. Have the application listen on `0.0.0.0`, then expose it:

```python theme={null}
vm.start()
port = vm.expose_local(guest_port=8080)
print(f"Application available at http://127.0.0.1:{port}")
```

HTTP, WebSockets, and application file transfers use QEMU forwarding on `slirp` or localhost forwarding on TAP. They do not require SSH or a guest agent when the application listens on the guest network address. An application bound only to the guest's `127.0.0.1` needs `guest_loopback=True`, which routes through guest SSH.

Dynamic exposures keep their existing lifetime, so recreate them after pause, stop, or restore.

## Policy lifetime

The policy is saved with the sandbox and stays unchanged across `start`, network repair, `restart`, and supported snapshot restore. Reconnecting to a sandbox by `vm_id` also inherits the saved policy.

Policy changes apply only to newly created sandboxes. Existing sandboxes keep their prior policy; to change a running sandbox, create a new one with the desired `internet_settings`.

After upgrading Celesto, running sandboxes keep their current network rules until Celesto repairs their networking or they restart. Restart them to apply the updated baseline isolation.

## Snapshots and imported disks

A disk imported as a new image receives the policy from its new VM configuration; the disk does not carry a network policy by itself.

QEMU shared folders continue to work with `off` and `restricted`. Their normal setup requirements still apply. QEMU snapshots require an isolated qcow2 disk and do not support shared folders.

If custom create and restore workflows share an inventory, pass the same state manager:

```python theme={null}
vm = Celesto.from_image(image, state_manager=inventory)
restored = Celesto.from_snapshot(snapshot_id, state_manager=inventory)
```

## Allow domains at startup

You can also allow domains on Firecracker private networking or QEMU TAP. This Linux Firecracker example keeps the command connection available through `vsock`:

```python theme={null}
with Celesto(
    backend="firecracker",
    comm_channel="vsock",
    internet_settings={"allowed_domains": ["api.example.com"]},
) as vm:
    vm.run("curl https://api.example.com")
```

Celesto resolves each name to IPv4 addresses during setup. It does not verify the hostname on every connection, and changing DNS answers can prevent an allowed service from working. Do not combine `allowed_domains` with `mode`. HTTP-method restrictions are not supported.

## Related

* [InternetSettings reference](/smolvm/api/internetsettings)
* [Port forwarding](/smolvm/features/port-forwarding)
* [Network configuration](/smolvm/concepts/networking)
* [Backend comparison](/smolvm/concepts/backends)


## Related topics

- [Security model](/smolvm/concepts/security.md)
- [Network configuration](/smolvm/concepts/networking.md)
- [Control internet access for AI agent sandboxes](/cloud/features/network-control.md)
- [Bridged networking](/smolvm/features/bridged-networking.md)
- [InternetSettings](/smolvm/api/internetsettings.md)
