---
title: Proxies
description: Route outbound sandbox traffic through an HTTP CONNECT or SOCKS proxy
icon: "route"
---

<Tooltip tip="Outbound proxies are not yet available on microsandbox cloud."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>

Configure one HTTP CONNECT, SOCKS4, or SOCKS5 proxy for outbound sandbox traffic. The guest connects to its normal destination; microsandbox routes eligible traffic through the proxy on the host.

Set `sandbox_defaults.outbound_proxy` in [global configuration](/configuration#sandbox_defaults) for a shared default. Administrators can enforce or clear it through [managed configuration](/enterprise/corporate-networking#route-sandbox-traffic), which takes precedence over per-sandbox CLI and SDK options.

## Supported proxies

| Proxy | Authentication | Traffic | Availability |
|-------|----------------|---------|--------------|
| HTTP CONNECT | Optional username and password | TCP | SDKs and CLI |
| SOCKS4 | None | TCP | SDKs and CLI |
| SOCKS4 | Optional user ID | TCP | SDKs and CLI |
| SOCKS5 | None | TCP and non-DNS UDP | SDKs and CLI |
| SOCKS5 | Optional username and password | TCP and non-DNS UDP | SDKs and CLI |

You can configure only one proxy for a sandbox. A SOCKS4 user ID identifies the caller; it is not a password.

## Configure a proxy

<CodeGroup>
```typescript TypeScript
import { Sandbox } from "microsandbox";

await using sb = await Sandbox.builder("proxied")
  .image("python")
  .proxy((p) => p.socks5("127.0.0.1:1080"))
  .create();
```

```rust Rust
use microsandbox::Sandbox;

let sb = Sandbox::builder("proxied")
    .image("python")
    .proxy(|p| p.socks5("127.0.0.1:1080"))
    .create()
    .await?;
```

```python Python
from microsandbox import OutboundProxy, Sandbox

sb = await Sandbox.create(
    "proxied",
    image="python",
    proxy=OutboundProxy.socks5("127.0.0.1:1080"),
)
```

```go Go
sb, err := m.CreateSandbox(ctx, "proxied",
    m.WithImage("python"),
    m.WithProxy(m.SOCKS5Proxy("127.0.0.1:1080")),
)
```

```ruby Ruby
sb = Microsandbox::Sandbox.create(
  "proxied",
  image: "python",
  proxy: Microsandbox::OutboundProxy.socks5("127.0.0.1:1080")
)
```

```bash CLI
# Choose one:
msb create python --name proxied --proxy http://127.0.0.1:3128
msb create python --name proxied --proxy socks4://127.0.0.1:1080
msb create python --name proxied --proxy socks5://127.0.0.1:1080
```
</CodeGroup>

SDK addresses use `IP:port`. The `msb run` and `msb create` commands accept `--proxy http://IP:port`, `socks4://IP:port`, or `socks5://IP:port`. Proxy URIs reject user information, paths, query parameters, and fragments; SOCKS authentication uses separate CLI flags.

## HTTP CONNECT

HTTP CONNECT opens a TCP tunnel through an HTTP proxy. It supports optional HTTP Basic authentication and TCP only; UDP is unsupported. microsandbox resolves and checks the destination using its normal DNS and egress policy before sending the destination IP and port in the CONNECT request. The proxy address itself must be an IP address with a port.

The selected `msb` runtime must support HTTP CONNECT. When using an older runtime, the SDK requests an upgrade before creating or replacing a sandbox.

<CodeGroup>
```typescript TypeScript
.proxy((p) => p.httpConnect("127.0.0.1:3128"))
```

```rust Rust
.proxy(|p| p.http_connect("127.0.0.1:3128"))
```

```python Python
proxy=OutboundProxy.http_connect("127.0.0.1:3128")
```

```go Go
m.WithProxy(m.HTTPConnectProxy("127.0.0.1:3128"))
```

```ruby Ruby
proxy = Microsandbox::OutboundProxy.http_connect("127.0.0.1:3128")
sandbox = Microsandbox::Sandbox.create("proxied", image: "alpine", proxy: proxy)
```

```bash CLI
msb run alpine --proxy http://127.0.0.1:3128
```
</CodeGroup>

## SOCKS4 user ID

Add an optional user ID through an SDK or `--socks4-user-id` in the CLI.

<CodeGroup>
```typescript TypeScript
.proxy((p) => p.socks4("127.0.0.1:1080").userId("sandbox"))
```

```rust Rust
.proxy(|p| p.socks4("127.0.0.1:1080").user_id("sandbox"))
```

```python Python
proxy=OutboundProxy.socks4("127.0.0.1:1080", user_id="sandbox")
```

```go Go
m.WithProxy(m.SOCKS4Proxy(
    "127.0.0.1:1080",
    m.SOCKS4ProxyOptions{UserID: "sandbox"},
))
```

```ruby Ruby
proxy = Microsandbox::OutboundProxy.socks4("127.0.0.1:1080").user_id("sandbox")
```

```bash CLI
msb run alpine \
  --proxy socks4://127.0.0.1:1080 \
  --socks4-user-id sandbox
```
</CodeGroup>

The user ID must contain 1–255 bytes and cannot contain a null byte. Omit it to use SOCKS4 without a user ID.

## SOCKS5 credentials

SOCKS5 supports optional username/password authentication. Passwords are loaded from a host environment variable rather than placed directly in configuration.

<CodeGroup>
```typescript TypeScript
.proxy((proxy) =>
  proxy.socks5("127.0.0.1:1080").credentials(
    "sandbox",
    SecretSource.env("SOCKS5_PASSWORD"),
  ),
)
```

```rust Rust
.proxy(|proxy| {
    proxy.socks5("127.0.0.1:1080").credentials(
        "sandbox",
        SecretSource::env("SOCKS5_PASSWORD"),
    )
})
```

```python Python
proxy = OutboundProxy.socks5("127.0.0.1:1080").credentials(
    "sandbox",
    SecretSource.env("SOCKS5_PASSWORD"),
)
```

```go Go
proxy := m.SOCKS5Proxy("127.0.0.1:1080").Credentials(
    "sandbox",
    m.SecretSourceEnv("SOCKS5_PASSWORD"),
)
m.WithProxy(proxy)
```

```ruby Ruby
proxy = Microsandbox::OutboundProxy.socks5("127.0.0.1:1080").credentials(
  "sandbox",
  Microsandbox::SecretSource.env("SOCKS5_PASSWORD")
)
```

```bash CLI
msb run alpine \
  --proxy socks5://127.0.0.1:1080 \
  --socks5-username sandbox \
  --socks5-password-env SOCKS5_PASSWORD
```
</CodeGroup>

- **Password source:** Set the password in a host environment variable, the only supported source. Configuration stores only the variable name, such as `SOCKS5_PASSWORD`, never the password.
- **When changes apply:** The password is read when the sandbox starts. Restart the sandbox after changing it.
- **Requirements:** The username and password must each contain 1–255 bytes. Startup fails if the password variable is missing, empty, or invalid.

<Warning>
  SOCKS5 authentication does not encrypt credentials in transit. Use a trusted local or private proxy, or encrypt the connection separately.
</Warning>

## HTTP CONNECT credentials

HTTP CONNECT supports optional HTTP Basic authentication. Passwords are loaded from a host environment variable rather than placed directly in configuration.

<CodeGroup>
```typescript TypeScript
.proxy((proxy) =>
  proxy.httpConnect("127.0.0.1:3128").credentials(
    "sandbox",
    SecretSource.env("HTTP_CONNECT_PASSWORD"),
  ),
)
```

```rust Rust
.proxy(|proxy| {
    proxy.http_connect("127.0.0.1:3128").credentials(
        "sandbox",
        SecretSource::env("HTTP_CONNECT_PASSWORD"),
    )
})
```

```python Python
proxy = OutboundProxy.http_connect("127.0.0.1:3128").credentials(
    "sandbox",
    SecretSource.env("HTTP_CONNECT_PASSWORD"),
)
```

```go Go
proxy := m.HTTPConnectProxy("127.0.0.1:3128").Credentials(
    "sandbox",
    m.SecretSourceEnv("HTTP_CONNECT_PASSWORD"),
)
m.WithProxy(proxy)
```

```ruby Ruby
proxy = Microsandbox::OutboundProxy.http_connect("127.0.0.1:3128").credentials(
  "sandbox",
  Microsandbox::SecretSource.env("HTTP_CONNECT_PASSWORD")
)
```

```bash CLI
msb run alpine \
  --proxy http://127.0.0.1:3128 \
  --http-connect-username sandbox \
  --http-connect-password-env HTTP_CONNECT_PASSWORD
```
</CodeGroup>

- **Password source:** Set the password in a host environment variable, the only supported source. Configuration stores only the variable name, such as `HTTP_CONNECT_PASSWORD`, never the password.
- **When changes apply:** The password is read when the sandbox starts. Restart the sandbox after changing it.
- **Username:** RFC 7617 permits an empty username for token-only authentication. A non-empty username must not contain `:` or control characters.
- **Password:** The resolved password must not be empty.
- **407 responses:** A proxy that requires authentication is refused instead of retried without credentials. The error distinguishes missing credentials from rejected credentials.
- **Runtime support:** The selected `msb` runtime must advertise the HTTP CONNECT authentication capability. An older runtime fails the launch with an upgrade-required error instead of silently connecting unauthenticated.

<Warning>
  HTTP Basic authentication does not encrypt credentials in transit. Use a trusted local or private proxy, or encrypt the connection separately.
</Warning>

## Behavior and limits

- Network policy is evaluated against the sandbox's actual destination before the proxy connection is opened.
- HTTP CONNECT and SOCKS4 support TCP only. Non-DNS UDP is blocked while either is configured; SOCKS4 also cannot reach IPv6 destinations.
- SOCKS5 uses `CONNECT` for TCP and `UDP ASSOCIATE` for non-DNS UDP.
- DNS uses microsandbox's DNS forwarder instead of the configured proxy. This includes plain DNS, DNS-over-TCP, and DNS-over-TLS.
- Connections to `host.microsandbox.internal` bypass the proxy and continue to target the microsandbox host.
- Each TCP connection opens its own proxy connection and handshake. Each UDP flow opens its own SOCKS5 control connection and UDP association.
- HTTP CONNECT authentication uses HTTP Basic credentials on the CONNECT request; see [HTTP CONNECT credentials](#http-connect-credentials) for the 407 behavior.
- TLS interception and secret injection continue to work as configured.

## Reference

For exact proxy APIs, see [TypeScript](/sdk/typescript/proxies), [Rust](/sdk/rust/proxies), [Python](/sdk/python/proxies), [Go](/sdk/go/proxies), or [Ruby](/sdk/ruby/networking#outboundproxy). For CLI flags, see [Sandbox commands](/cli/sandbox-commands#outbound-proxy).

## Related

- [TLS interception](/networking/tls)
- [Network overview](/networking/overview)
