出网请求头转换

更新时间:
复制 MD 格式

通过 network.rules,云沙箱向指定域名发起 HTTP/HTTPS 出网请求时,平台可以为请求添加或覆盖请求头,或者替换请求头值中的凭据占位符。真实凭据无需以环境变量、文件或代码形式进入云沙箱。

工作原理

云沙箱的出网请求经过节点出网代理时,平台按目标域名匹配 network.rules,并为命中的请求添加、覆盖请求头,或替换请求头值中的占位符。

对于 HTTP 请求,平台在节点出网代理处直接修改请求头。对于 HTTPS 请求,平台需要先解密才能修改请求头,因此会在节点出网代理处对 HTTPS 做 TLS 检查,使用平台 CA 为目标域名动态签发证书,并校验真实上游服务出示的 HTTPS 证书。云沙箱客户端需要信任平台 CA,否则 HTTPS 请求会返回证书错误,模板要求参见前提条件。

前提条件

  • 在控制面运行环境准备真实凭据。本文示例从环境变量 API_TOKEN 读取凭据,真实凭据无需进入云沙箱。

  • 如果云沙箱内代码通过 HTTPS 访问目标域名,模板需包含平台 CA:

    • 官方模板及受支持的 Debian/Ubuntu 自定义模板已内置平台 CA,curl、Python requests、Node.js 开箱即用。

    • 官方镜像版本至少为 v0.0.44:

      • fc-e2b-registry.${regionId}.cr.aliyuncs.com/runtime/base:v0.0.44

      • fc-e2b-registry.${regionId}.cr.aliyuncs.com/runtime/code-interpreter-v1:v0.0.44

    • 自定义镜像的构建时间需晚于 2026-08-15 的平台发版。更早的镜像不会自动接收平台 CA。

选择转换方式

方式

适用场景

云沙箱侧的请求头构造方式

整请求头注入

控制面已知完整请求头,例如 Authorization: Bearer ...。

云沙箱可以完全不构造该请求头。

请求头值占位符替换

第三方 SDK 或云沙箱代码需要动态构造请求头,仅需隐藏其中的敏感片段。

发出请求头结构及非敏感占位符。

当同一请求头同时命中两种方式时,平台先执行占位符替换,再执行整请求头注入,最终以注入值为准。

整请求头注入

Node.js

import { Sandbox } from "e2b";

const token = process.env.API_TOKEN;
if (!token) throw new Error("API_TOKEN is required");

const sandbox = await Sandbox.create({
  network: {
    allowOut: ["api.example.com"],
    denyOut: ["0.0.0.0/0"],
    rules: {
      "api.example.com": [
        {
          transform: {
            headers: {
              Authorization: `Bearer ${token}`,
            },
          },
        },
      ],
    },
  },
});
console.log(`[create] Sandbox created: ${sandbox.sandboxId}`);

// 沙箱内的代码调用 https://api.example.com 时,
// 平台会自动注入 Authorization,业务代码无需设置该请求头。

Python

import os

from e2b import Sandbox

token = os.environ["API_TOKEN"]

sandbox = Sandbox.create(
    network={
        "allow_out": ["api.example.com"],
        "deny_out": ["0.0.0.0/0"],
        "rules": {
            "api.example.com": [
                {
                    "transform": {
                        "headers": {"Authorization": f"Bearer {token}"}
                    }
                }
            ]
        },
    },
)
print(f"[create] Sandbox created: {sandbox.sandbox_id}")

云沙箱内代码按原样调用 https://api.example.com,无需设置 Authorization。目标服务会收到由平台注入的请求头。

请求头值占位符替换

当前 E2B SDK 未暴露独立的 replacement 字段。云沙箱(FC Agent Sandbox)通过一个保留的请求头键承载替换规则,其值必须为包含替换数组的 JSON 字符串:

fc.sandbox.network.header-value-replacements

该键仅用于创建或更新规则,不会作为真实 HTTP 请求头发送给目标服务。

Node.js

import { Sandbox } from "e2b";

const token = process.env.API_TOKEN;
if (!token) throw new Error("API_TOKEN is required");

const replacements = JSON.stringify([
  { placeholder: "TOKEN_PLACEHOLDER", value: token },
]);

const sandbox = await Sandbox.create({
  network: {
    allowOut: ["api.example.com"],
    denyOut: ["0.0.0.0/0"],
    rules: {
      "api.example.com": [
        {
          transform: {
            headers: {
              "fc.sandbox.network.header-value-replacements": replacements,
            },
          },
        },
      ],
    },
  },
});

Python

import json
import os

from e2b import Sandbox

token = os.environ["API_TOKEN"]
carrier = json.dumps(
    [{"placeholder": "TOKEN_PLACEHOLDER", "value": token}]
)

sandbox = Sandbox.create(
    network={
        "allow_out": ["api.example.com"],
        "deny_out": ["0.0.0.0/0"],
        "rules": {
            "api.example.com": [
                {
                    "transform": {
                        "headers": {
                            "fc.sandbox.network.header-value-replacements": carrier
                        }
                    }
                }
            ]
        },
    },
)

配置完成后,云沙箱代码或第三方 SDK 发出:

Authorization: Bearer TOKEN_PLACEHOLDER

目标服务收到:

Authorization: Bearer 真实 token

替换区分大小写,同一请求头值内的所有匹配项都会被替换。扫描只执行一次——生成的输出不会触发再次替换——未匹配的占位符会按原样发送给目标服务。

运行时更新规则

无需重建云沙箱即可修改 network.rules:Node.js 调用 updateNetwork,Python 调用 update_network。PUT /sandboxes/{id}/network 为整体替换而非增量更新,每次更新都必须提交完整的 allowOut、denyOut 和 rules。省略 rules,或传入 null 或 {},将清空现有规则。

更新失败时,原规则继续生效。云沙箱暂停期间网络规则会被保留,暂停状态下也可以更新 network.rules,云沙箱恢复后以最新规则为准。

Node.js

import { Sandbox } from "e2b";

const sandbox = await Sandbox.create({
  network: {
    allowOut: ["api.example.com"],
    denyOut: ["0.0.0.0/0"],
  },
});
console.log(`[create] Sandbox created: ${sandbox.sandboxId}`);

// 后续追加规则
await sandbox.updateNetwork({
  allowOut: ["api.example.com"],
  denyOut: ["0.0.0.0/0"],
  rules: {
    "api.example.com": [
      {
        transform: {
          headers: {
            Authorization: `Bearer ${process.env.API_TOKEN}`,
          },
        },
      },
    ],
  },
});
console.log("[update] network.rules applied");

// 清空规则
await sandbox.updateNetwork({
  allowOut: ["api.example.com"],
  denyOut: ["0.0.0.0/0"],
});
console.log("[update] network.rules cleared");

Python

import os

from e2b import Sandbox

sandbox = Sandbox.create(
    network={
        "allow_out": ["api.example.com"],
        "deny_out": ["0.0.0.0/0"],
    },
)
print(f"[create] Sandbox created: {sandbox.sandbox_id}")

# 后续追加规则
sandbox.update_network({
    "allow_out": ["api.example.com"],
    "deny_out": ["0.0.0.0/0"],
    "rules": {
        "api.example.com": [
            {
                "transform": {
                    "headers": {
                        "Authorization": f"Bearer {os.environ['API_TOKEN']}"
                    }
                }
            }
        ]
    },
})
print("[update] network.rules applied")

# 清空规则
sandbox.update_network({
    "allow_out": ["api.example.com"],
    "deny_out": ["0.0.0.0/0"],
})
print("[update] network.rules cleared")

getInfo 或 GET /sandboxes/{id} 返回的 network.rules 反映当前生效的规则,可用于核对当前规则内容,也可作为后续更新的输入。响应中每条替换规则会被重新编码为保留请求头键承载的 JSON 字符串,真实 value 以明文返回。请勿将响应写入普通日志、工单或前端错误上报。

安全建议

  • 仅从可信控制面读取并提交真实凭据,禁止将密钥提交到代码仓库。

  • 使用密钥管理服务、CI 密钥或短期、已鉴权的业务凭据。

  • 优先使用 HTTPS。HTTP 请求一旦离开节点出网代理即为明文,凭据可能在传输期间泄露。

  • 使用短期、最小权限、按租户或按会话粒度可吊销的凭据。

  • 仅为真实目标配置精确域名,并确认目标不会回显或记录鉴权请求头。

  • 保护创建、更新、查询 API 的身份权限,避免打印完整的 network.rules。

  • 禁止将真实、可用的凭据放入占位符本身。

使用限制

network.rules 中,每个精确域名对应一个规则对象,规则对象通过 transform.headers 承载普通请求头或替换规则。相关限制如下:

项目

限制

目标域名

最多 10 个。仅精确域名,精确匹配,子域名不匹配。不支持通配符、IP、CIDR、URL、端口、路径。

单域名规则数

固定 1 条。

普通请求头

每条规则最多 20 个。请求头名:1~64 字节。请求头值:最长 2,048 字节。

序列化规则总大小

最长 64 KiB。

替换规则

单域名最多 16 条。单云沙箱最多 64 条。

占位符

8~128 字节。仅允许字母、数字、_、.、-。

替换值

1~2,048 字节。

占位符不得与真实值相同,不得重复,也不得是另一个占位符的子串。

以下类别的请求头不可配置,或在替换时被跳过:Host、Content-Length、Transfer-Encoding、Connection、Upgrade、代理鉴权请求头、x-envoy-*、x-forwarded-* 及其他路由或帧控制类请求头。受限集合可能随着平台版本变化,请勿依赖特定版本对这些请求头的行为。

常见问题

配置了 rules 仍然无法访问目标,为什么?

rules 不会开通网络访问。请确认目标已加入 allowOut,且 denyOut 未覆盖该目标。

请求头转换未生效,为什么?

先通过 getInfo 返回的 network.rules 确认规则已生效。如果规则配置正确,但目标服务仍未收到预期请求头,请逐项排查:

  • 域名匹配:目标域名仅支持精确匹配,子域名不匹配,且不支持通配符、IP、CIDR、URL、端口、路径。

  • 受限请求头:Host、Content-Length 等类别的请求头不可配置,或在替换时被跳过。

  • 占位符约束:替换区分大小写,未匹配的占位符会按原样发送给目标服务;占位符不得与真实值相同、不得重复、不得是另一个占位符的子串。

  • 规则清空:如果最近一次更新省略了 rules,或传入 null、{},现有规则已被清空。

HTTP 正常,但 HTTPS 返回证书错误,为什么?

平台需要解密 HTTPS 才能修改请求头,因此会在节点出网代理处对 HTTPS 做 TLS 检查,并使用平台 CA 为目标域名动态签发证书,详见工作原理。如果云沙箱客户端不信任平台 CA,请检查证书文件、模板版本以及对应语言的信任库。以下客户端通常需要额外配置信任:

  • Java:将 /usr/local/share/ca-certificates/e2b-ca.crt 导入 JVM cacerts 或应用信任库。

  • Firefox 或 NSS。

  • 仅读取 OpenSSL CApath 的应用。

  • 非 Debian/Ubuntu 的自定义镜像。

  • 使用私有信任库、证书固定或忽略系统环境变量的客户端。

    同时确认模板版本,过旧模板未注入平台 CA。官方镜像与自定义镜像的版本要求参见前提条件。