# 网络访问
<subtitle>控制并限制沙箱的出站互联网访问。</subtitle>

默认情况下，每个沙箱都拥有出站互联网访问权限。您可以控制和限制这种访问，以适应对安全敏感的工作负载——从简单的开关到细粒度的允许和拒绝列表。

要将沙箱内运行的服务暴露给外部世界，请参阅 [沙箱公开 URL](/docs/agent-sandbox/network/public-url.md)。

## 控制互联网访问

创建沙箱时，您可以使用 `allow_internet_access` 参数来控制沙箱是否可以访问互联网。默认情况下，互联网访问是启用的，但您可以为对安全敏感的工作负载禁用它。

```python
from ucloud_sandbox import Sandbox

# 创建启用互联网访问的沙箱（默认）
sandbox = Sandbox.create(allow_internet_access=True)

# 创建不带互联网访问的沙箱
isolated_sandbox = Sandbox.create(allow_internet_access=False)
```

当互联网访问被禁用时，沙箱无法建立出站网络连接，这为敏感代码执行提供了额外的安全保护层。

> 将 `allow_internet_access` 设置为假值等同于将 `network.deny_out` 设置为 `['0.0.0.0/0']`（拒绝所有流量）。

## 细粒度网络控制

要对网络访问进行更精细的控制，您可以使用 network 配置选项为出站流量指定允许和拒绝列表。

### 允许和拒绝列表

您可以指定沙箱允许使用的 IP 地址、CIDR 块或域名：

```python
from ucloud_sandbox import Sandbox

# 拒绝除特定 IP 外的所有流量
sandbox = Sandbox.create(
    network={
        "deny_out": lambda ctx: [ctx.all_traffic],  # ctx.all_traffic == "0.0.0.0/0"
        "allow_out": ["1.1.1.1", "8.8.8.0/24"]
    }
)

# 仅拒绝特定 IP
restricted_sandbox = Sandbox.create(
    network={
        "deny_out": ["8.8.8.8"]
    }
)
```

> 选择器回调（`lambda ctx: [ctx.all_traffic]`）是表达"所有流量"（`0.0.0.0/0`）的推荐方式。`ALL_TRAFFIC` 常量仍然导出以保持向后兼容。

### 基于域名的过滤

您可以通过在 `allow_out` 中指定主机名来允许对特定域名的流量。使用基于域名的过滤时，您必须在 `deny_out` 中拒绝所有其他流量。拒绝列表中不支持域名。

```python
from ucloud_sandbox import Sandbox

# 仅允许对 google.com 的流量
sandbox = Sandbox.create(
    network={
        "allow_out": ["google.com"],
        "deny_out": lambda ctx: [ctx.all_traffic]
    }
)
```

> 当使用任何域名时，默认名称服务器 `8.8.8.8` 会自动被允许，以确保正确的 DNS 解析。

您还可以使用通配符来允许某个域名的所有子域名：

```python
from ucloud_sandbox import Sandbox

# 允许对 mydomain.com 的任何子域名的流量
sandbox = Sandbox.create(
    network={
        "allow_out": ["*.mydomain.com"],
        "deny_out": lambda ctx: [ctx.all_traffic]
    }
)
```

您可以将域名与 IP 地址和 CIDR 块组合使用：

```python
from ucloud_sandbox import Sandbox

# 允许对特定域名和 IP 的流量
sandbox = Sandbox.create(
    network={
        "allow_out": ["api.example.com", "*.github.com", "8.8.8.8"],
        "deny_out": lambda ctx: [ctx.all_traffic]
    }
)
```

> 基于域名的过滤仅适用于 80 端口的 HTTP 流量（通过 Host 头检查）和 443 端口的 TLS 流量（通过 SNI 检查）。其他端口的流量仅使用基于 CIDR 的过滤。基于 UDP 的协议（如 QUIC/HTTP3）不支持域名过滤。

### 被阻止的 TCP 连接的行为

由于防火墙的设计，被阻止的连接从沙箱内部看可能显示为成功。

防火墙必须先接受连接，然后才能决定目标是否被允许。这意味着，从沙箱内部看，即使目标被拒绝，TCP 连接也可以成功并报告套接字已打开——但实际上没有任何数据包到达目标。

要验证流量是否到达目标，请检查应用层响应（例如 HTTP 状态码、TLS 握手或预期的协议字节），而不是依赖 TCP 连接成功。

这是当前出站流量从沙箱路由到防火墙的方式的限制，未来可能会改变。

### 优先级规则

当同时指定允许和拒绝规则时，**允许规则始终优先于**拒绝规则。这意味着如果一个 IP 地址同时出现在两个列表中，它将被允许。

```python
from ucloud_sandbox import Sandbox

# 尽管所有流量都被拒绝，1.1.1.1 和 8.8.8.8 仍被明确允许
sandbox = Sandbox.create(
    network={
        "deny_out": lambda ctx: [ctx.all_traffic],
        "allow_out": ["1.1.1.1", "8.8.8.8"]
    }
)
```

### 按主机的请求转换

> 按主机的请求转换目前处于公测阶段。您可以立即开始使用，无需申请访问权限。
> 
> 请注意，此功能仍在积极开发中，其功能和交互方式在此期间可能会发生变化。

您可以在 `network.rules` 下注册按主机的规则，以对匹配某个主机的出站请求应用转换（例如，注入 HTTP 头）。规则以主机为键，注册规则本身**不会**授予出站权限——该主机仍必须通过 `allow_out` 引用。

`transform.headers` 对象会原样通过网络发送，并由出站代理在匹配的 HTTP/HTTPS 请求上注入。

```python
from ucloud_sandbox import Sandbox

sandbox = Sandbox.create(
    network={
        # 仅允许对已注册规则的主机的出站流量
        "allow_out": lambda ctx: list(ctx.rules.keys()),
        # 拒绝所有其他流量
        "deny_out": lambda ctx: [ctx.all_traffic],
        # 注册按主机的规则
        "rules": {
            "api.example.com": [
                {
                    "transform": {
                        "headers": {"X-Header": "Content"},
                    },
                },
            ],
        },
    },
)
```

### 更新运行中沙箱的网络设置

您可以使用 `update_network` 更新已运行沙箱的网络配置。这会用提供的配置替换当前的出站规则，而无需重启沙箱。

```python
from ucloud_sandbox import Sandbox

sandbox = Sandbox.create()

# 收紧运行中沙箱的出站流量：阻止 8.8.8.8
sandbox.update_network({"deny_out": ["8.8.8.8"]})

# 替换为仅允许列表
sandbox.update_network({
    "deny_out": lambda ctx: [ctx.all_traffic],
    "allow_out": ["api.example.com"],
})

# 无需重新创建沙箱即可切换互联网访问
sandbox.update_network({"allow_internet_access": False})
```

> `update_network` 会**替换**当前的出站配置——它不会与现有规则合并。使用空对象调用它（`update_network({})`）会清除创建时设置的所有允许和拒绝规则。

诸如 `allow_public_traffic`、`mask_request_host` 以及 `network.rules` 中的网络规则等仅创建时可用的选项，在沙箱创建后无法更改。
