应用端口
E2B 网关把 {port}-{sandboxID}.<domain> 的 HTTP 与 WebSocket 请求转发到 sandbox 内 loopback 上的对应端口。本页介绍怎样访问端口、怎样把端口设为私有、请求怎样到达应用,以及桌面与 Chrome DevTools 的使用方式。
概述
网关启动时通过 KIBOTOS_E2B_DOMAIN 指定 sandbox 域名,例如 sandbox.example。之后:
| 域名 | 用途 |
|---|---|
api.sandbox.example | 控制 API |
49983-{sandboxID}.sandbox.example | envd 协议,由单独的监听地址处理 |
{port}-{sandboxID}.sandbox.example | 应用端口,转发到 sandbox 内 loopback 上的对应端口 |
- 应用端口与控制 API 共用同一个监听地址,没有额外的端口。
port是 1 到 65535 的十进制数字,sandboxID是 API 返回的 sandbox ID。- 通配域名解析、TLS 证书与续期、反向代理对 WebSocket 升级和流式响应的支持由部署方提供,见配置反向代理。
公开与私有端口
与 E2B 一样,应用端口默认公开,由创建参数 network.allowPublicTraffic 决定:
- 没有
network字段,或network中没有allowPublicTraffic(例如只有出网相关字段),端口公开。 - 只有显式的
allowPublicTraffic: false才让端口变为私有,访问时必须携带 traffic token。
下面的创建参数把端口设为私有,连接参数与示例相同:
const sandbox = await Sandbox.create('kibotos-minimal', {
// apiKey、domain、apiUrl 与示例相同
network: { allowPublicTraffic: false },
});这个设置在创建时确定。GET /sandboxes/{id} 与列表接口回显 network.allowPublicTraffic,值为创建时的设置。哪些 SDK 调用保留回显的字段,见 Sandbox 与生命周期。
traffic token
- 私有 sandbox 的请求必须携带
e2b-traffic-access-token。 - 公开 sandbox 可以不带 token;带了错误或重复的 token 仍返回 401。
- API key 与 envd token 不能代替 traffic token。
下面的请求访问私有 sandbox 的 8080 端口:
curl -H "e2b-traffic-access-token: $traffic_token" "https://8080-$sandbox_id.sandbox.example/"- 带了 token 却验签不通过时,网关直接返回 401,不查 sandbox 是否存在。
- token 正确、或公开 sandbox 不带 token 时,sandbox 不存在返回 404。
- sandbox 这次执行是否还在,由 node 判定。执行结束后 node 拒绝旧凭证,网关返回 401,SDK 重新 connect 即可。
Host 头
默认情况下,应用收到请求原始的 Host。创建参数 network.maskRequestHost 可以改写它:
const sandbox = await Sandbox.create('kibotos-minimal', {
// apiKey、domain、apiUrl 与示例相同
network: { maskRequestHost: 'localhost:${PORT}' },
});- 合法的非空字符串会持久化,并改写应用端口 HTTP 与 WebSocket 请求的 Host,其中的
${PORT}替换为实际端口。 - 缺省、
null或空字符串时保留原始 Host。 - 值无效或类型错误返回 400。
- 这个选项只能在创建时设置,不影响出网策略,也不作用于 envd 端口。
GET /sandboxes/{id}与列表接口回显network.maskRequestHost,值为创建时的设置;为空时不回显。
Host 的处理与 E2B 官方实现(infra ee356007d2362150895f024239d1d7e2e41114aa 的 pool/client.go)一致:只有创建时设置了 maskRequestHost 才改写。网关不会固定改写为 localhost。
转发行为
应用收到的请求
- 保留原始的 URL 路径与查询字符串、应用自己的
Authorization以及其他端到端的请求头;Host 也保留,除非maskRequestHost改写了它。 - 去掉 hop-by-hop 头、
Connection头中列出的头,以及 traffic token、envd token、API key 和网关内部的路由头。 - Kibotos 的会话凭证只用于连接 node,不会出现在应用请求或日志里。
- 网关不重放请求。应用返回 401 或 403 后是否重试由调用方决定。
HTTP
- 每个请求建立一条到 guest 的连接,不复用,也不重试。
- HTTP/1 请求带请求体时,网关在处理认证之前就允许双向传输。这样 401、503 或应用的早期响应可以在上传结束前返回,不会因为等待请求体而死锁。
- 上传与下载并行进行,背压向两端传递。请求体写完后关闭写方向;读到 guest 端的 EOF 后确认连接正常结束。
- 响应不预先声明
Content-Length。传输中途出错时 HTTP 响应会被截断。HEAD、204、304 等没有响应体的响应在确认连接正常结束后才发送响应头。
WebSocket
- 握手与数据帧原样转发。客户端关闭写方向时只关闭到 guest 的写方向,应用仍可以继续发送数据。
- 升级为 WebSocket 之后发生错误只能关闭连接,网关不会伪造关闭帧或再发送 HTTP 状态码。
空闲期限
应用端口上的一条连接,两个方向都没有字节达到 15 分钟时,网关结束它。
重要
与 E2B 不同,在 Kibotos 上 15 分钟完全没有数据的 WebSocket 会被断开。上游只在两次请求之间有空闲上限,对升级后的连接不设期限。需要长时间安静的应用要自己发心跳。
- 只要有字节在走,连接就不受这个期限影响。
- 客户端暂停读取时,数据等它恢复,不会被截断。
连接何时断开
以下事件会断开进行中的连接:请求被取消、sandbox 被删除、网关关闭,以及 sandbox 的执行结束或数据面凭证被撤销。
- 会话凭证的有效期只限制新建连接。已建立的连接不会因为凭证到期而断开,网关也不设置固定的连接时长上限。
- 执行结束与凭证撤销由 node 断开连接,网关不轮询 sandbox 的状态。
timeout请求延长有效期不影响已有连接;缩短有效期后,由 ctrl 在到期时停止 sandbox,连接随之断开。网关自己不保存到期时间,也不执行到期动作。
会话凭证
网关只通过 node 建立的服务连接到达 guest。它不解析宿主机网络,不直接连接 guest 的 IP,也没有自己的隧道协议。
网关按(sandbox,端口)缓存一张只包含该端口的 SERVICE_CONNECT 会话凭证访问数据面用的短期凭证。向 ctrl 申请,同时得到运行这个 Workspace 的 node 的地址。,生命周期跟随这次执行(lifetime = EXECUTION)。同一实例第一次访问某个端口时向 ctrl 申请一次,之后直接用缓存建立到 guest 的服务连接。
node 拒绝这张凭证时:
- 网关丢掉它并马上向 ctrl 换一张。ctrl 表明执行已经变了时返回 401,否则返回 502,下一个请求用新凭证。
- 新凭证仍被拒绝时,这个端口先等 1 秒才再向 ctrl 申请,之后每次加倍,最长 30 秒。等待期间的请求直接返回 502。
- node 正常建立一次连接后恢复。
状态码
| 情况 | 状态码 |
|---|---|
| 查询 sandbox 状态失败或 Kibotos 暂时不可用 | 503 |
| token 已撤销,或 sandbox 已重启 | 401 |
| node 拒绝会话凭证而执行没有变化,或正处于会话凭证一节所述的等待期 | 502 |
只有 401 表示调用方需要刷新 token。基础设施故障返回 503,避免调用方无意义地刷新。
桌面与 Chrome DevTools
下面的说明针对 Memoh 这类通过 6080、6081 端口使用桌面和浏览器的调用方:
- 6080 是 guest 内 noVNC/websockify 的桌面入口,需要 guest 镜像里有 X 桌面、VNC 服务和 noVNC。网关只转发,不提供桌面。
- 6081 是镜像内 websockify 的端口网关。
/?token=9222这类查询参数是它选择目标端口的方式,不是网关的 traffic token,网关原样传递。websockify 负责把 WebSocket 帧接到 guest loopback。 - 网关不改写 Chrome DevTools 的 discovery JSON。调用方通常解析
webSocketDebuggerUrl后只取路径和查询,再通过 6081 连接 9222。 - 经 6081 转发时内层请求的 Host 是 loopback,Chromium 会接受;直接访问公开的 9222 时 Chromium 可能因为 Host 不是 loopback 而拒绝。这是 Chromium 的行为,网关不会伪装 Host。
- 镜像里没有 6081 时,调用方可以直接访问公开端口,但不能保证 Chromium 接受。这些能力需要用真实镜像分别验证。
下一步
- E2B 兼容:支持的 SDK 能力与不支持的能力。
- 网络:sandbox 的出网策略。
- Sandbox 与生命周期:暂停、恢复与到期,它们会断开端口上的连接。
- 服务与端口:用
kibo或原生 API 访问 Workspace 内的端口。