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

# Control sandbox internet access

> Set an egress allowlist for local Linux sandboxes, allow specific destination addresses, or turn outbound internet access off.

You can choose which services your sandbox can contact. Give an agent access to the services its task needs, or turn internet access off so it works with files and tools already available inside the sandbox.

An **egress allowlist** is a list of destinations the sandbox can connect to. All other outbound destinations are blocked. Set it with `internet_settings` when you create a local sandbox with the Python SDK (software development kit).

> [!NOTE]
>
> Destination allowlists are available for local Linux sandboxes using Firecracker or QEMU with TAP networking, a connection through your Linux host. Cloud computers offer `open` and `off` settings through a separate [Network Control policy](https://celesto.ai/docs/cloud/features/network-control.md).

## 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 IPv4 addresses or network ranges the task needs. IPv4 addresses identify destinations using four numbers, such as `203.0.113.10`. This mode requires Firecracker on Linux with `comm_channel="vsock"`, a direct command connection separate from the sandbox's network, or explicit QEMU TAP networking on Linux.

### Set an egress allowlist on Linux

Complete [Celesto installation](https://celesto.ai/docs/celesto/installation.md) on your Linux machine first. Replace `203.0.113.10` below with your service's IPv4 address before running this example. Celesto applies the rules on your Linux host before the sandbox starts, so administrator access inside the sandbox keeps the same network restrictions.

```python egress_allowlist.py theme={null}
from celesto import Celesto


with Celesto(
    backend="firecracker",
    comm_channel="vsock",
    internet_settings={
        "mode": "restricted",
        "allowed_cidrs": ["203.0.113.10/32"],
    },
) as vm:
    result = vm.run("echo 'Sandbox ready with the destination allowlist'")
    if result.exit_code != 0:
        raise RuntimeError(result.stderr or result.stdout)
    print(result.stdout.strip())
```

Run it on your Linux machine:

```bash theme={null}
python3 egress_allowlist.py
```

> [!TIP]
>
> The script prints `Sandbox ready with the destination allowlist`. Commands remain available through the direct connection while outbound traffic follows your allowlist.

To check access for your workload, run its connection command with `vm.run(...)` against the allowed service, then against a reachable service outside the list. The allowed connection should succeed; the other should fail. Set a connection timeout in your command so a blocked connection returns promptly.

### Use QEMU with an existing network setup

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](https://celesto.ai/docs/celesto/concepts/networking.md) 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](https://celesto.ai/docs/celesto/api/internetsettings.md)
* [Port forwarding](https://celesto.ai/docs/celesto/features/port-forwarding.md)
* [Network configuration](https://celesto.ai/docs/celesto/concepts/networking.md)
* [Backend comparison](https://celesto.ai/docs/celesto/concepts/backends.md)


## Related topics

- [Control internet access for AI agent sandboxes](https://celesto.ai/docs/cloud/features/network-control.md)
- [Network configuration](https://celesto.ai/docs/celesto/concepts/networking.md)
- [InternetSettings](https://celesto.ai/docs/celesto/api/internetsettings.md)
- [Control channel](https://celesto.ai/docs/celesto/concepts/control-channel.md)
- [Celesto: secure microVM sandboxes for AI agents](https://celesto.ai/docs/celesto/introduction.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.