数据截至 (上游 commit 415259e527d2)
06 — 网络平面:入站路由、出站策略与凭证保险箱
本章讲什么: 前几章讲了沙箱怎么被创建、命令怎么在里面跑。这一章讲网络边界——两个方向的问题: 别人怎么访问到沙箱里跑的服务(入站 ingress),以及沙箱能访问外面的谁(出站 egress)。 外加一个精巧的东西:凭证保险箱,让沙箱里的 AI 工作负载能带着 API 密钥去调外部服务, 却始终看不到密钥本身。数据面主要是两个 Go 组件
components/ingress/和components/egress/, 控制面(Python server)在两侧各搭一座桥。
1. 先建立直觉(零基础也能懂)
沙箱是一个隔离的容器。里面可能跑了一个 Web 服务(比如 agent 起的 python -m http.server 8080),
你想从外面访问它;里面的 agent 也可能想 curl https://api.openai.com。这两件事都得穿过一道墙。
- 入站(ingress): 外部请求 → 网关 → 找到「哪个沙箱的哪个端口」→ 反代进去。 难点是怎么在一个共享网关上把请求路由到成千上万个沙箱,还得防止任意人猜个 ID 就访问到你的内部端口。
- 出站(egress): 沙箱发起的连接 → 一道策略闸 → 放行或拦 截。 难点是在容器内透明地拦下所有 DNS 和 TCP,按域名规则判定,而不需要工作负载配合。
- 凭证保险箱(Credential Vault): 出站路上有个 TLS 中间人,能在特定请求里偷偷塞进真实密钥。 agent 发一个「裸」请求(不带 Authorization),密钥由出站边车注入。这样密钥不进沙箱、不进 prompt、不会泄漏。
一句类比:入站像小区门禁(得刷对的签名门卡才让进,门卡还有有效期); 出站像海关(每个包裹按白名单查验放行);凭证保险箱像保税仓的报关代理(帮你在货物上贴对的关税单,你自己没碰过单子)。
2. 顶层全景(它大概怎么转)
怎么读这张图: 左边是「访问沙箱」的入站方向,右边是「沙箱访问外界」的出站方向,中间是被保护的沙箱。 控制面(Python server)不在数据路径上,只负责下发配置 + 签发凭据。
入站 ingress 沙箱 出站 egress
┌───────────────────────┐ ┌───────────────┐ ┌──────────────────────────┐
外部 │ ingress 网关 │ │ 沙箱容器 │ │ egress 边车 │
请求→│ ① 解析路由(host/uri) │──反代→ │ 用户服务:8080 │ │ ② DNS 拦截 15353 │
│ ② 校验签名/token │ │ agent 工作负载 │─出站→│ ③ nft L3 放行/拦截 │
└───────────────────────┘ └───────────────┘ │ ④ mitmproxy TLS 中间人 │
▲ ▲ │ └ 凭证注入 │
│下发 endpoint/签名密钥 │下发 egress 策略 │ │
┌────────┴──────────────────────────────┴───────────────┴──────────────────────────┐
│ 控制面 Python server:签名(services/signing.py)、反代兜底(api/proxy.py)、 │
│ 凭证/策略下发、renew-intent 续期消费 │
└───────────────────────────────────────────────────────────────────────────────────┘
三大件各自的职责:
| 组件 | 干什么 | 在哪 |
|---|---|---|
| ingress 网关 | 把外部请求按 sandbox_id + port 反代进沙箱,校验签名路由 | components/ingress/ |
| egress 边车 | 拦 DNS、按策略放行/拦截、TLS 中间人、注入凭证 | components/egress/ |
| 控制面 server | 签发签名路由、可选地自己反代、下发策略/凭证、续期 | server/opensandbox_server/ |
两条主线,后面各展开一节:
- 入站主线(§3、§4):请求带着一个「路由标签」进来 → 网关解析出沙箱/端口 → 校验访问凭据 → 反代。
- 出站主线(§6、§7、§8):沙箱发 DNS/TCP → 被 iptables 透明重定向到边车 → DNS 按域名策略判定 → (dns+nft 模式)把放行域名的 IP 加进 nft 动态允许集 → TLS 流量过 mitmproxy →(若命中绑定)注入凭证。