Kibotos

应用端口

E2B 网关把 {port}-{sandboxID}.<domain> 的 HTTP 与 WebSocket 请求转发到 sandbox 内 loopback 上的对应端口。本页介绍怎样访问端口、怎样把端口设为私有、请求怎样到达应用,以及桌面与 Chrome DevTools 的使用方式。

概述

网关启动时通过 KIBOTOS_E2B_DOMAIN 指定 sandbox 域名,例如 sandbox.example。之后:

域名用途
api.sandbox.example控制 API
49983-{sandboxID}.sandbox.exampleenvd 协议,由单独的监听地址处理
{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 拒绝这张凭证时:

  1. 网关丢掉它并马上向 ctrl 换一张。ctrl 表明执行已经变了时返回 401,否则返回 502,下一个请求用新凭证。
  2. 新凭证仍被拒绝时,这个端口先等 1 秒才再向 ctrl 申请,之后每次加倍,最长 30 秒。等待期间的请求直接返回 502。
  3. 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 接受。这些能力需要用真实镜像分别验证。

下一步

本页内容