CubeSandbox 安全沙箱网络深度解析:eBPF 内核数据面与 L7 代理的双层防御体系
【免费下载链接】CubeSandboxInstant, Concurrent, Secure & Lightweight Sandbox for AI Agents.项目地址: https://gitcode.com/GitHub_Trending/cu/CubeSandbox
AI Agent 赋予机器自主执行能力(写代码、调 API、操作浏览器、执行系统命令),同时也打开了数据外泄与凭据滥用的潘多拉魔盒。CubeSandbox 在 KVM MicroVM 隔离的基础上,构建了一套从虚拟交换到应用层审计的端到端网络安全体系:内核侧由 eBPF 承担 L4 转发与策略执行,用户态由 OpenResty 承担 L7 路由与深度检测。本文以 CubeVS、CubeProxy、CubeEgress 三大核心组件为主线,结合 CubeNet(CubeVS)、CubeProxy、CubeEgress 的源码实现,剖析其设计思路、策略语义与底层工作原理,帮助你理解并实际运用这套"开放执行 + 安全可控"的沙箱网络方案。
1. 业务背景与安全需求
1.1 AI Agent 带来的安全挑战
AI Agent 正从"对话助手"演化为"自主执行器"——它们可以编写代码、调用 API、操作浏览器、运行系统命令。这种自主性带来效率提升的同时,也引入前所未有的安全风险:
| 风险维度 | 典型场景 | 潜在影响 |
|---|---|---|
| 代码执行风险 | LLM 生成的代码包含恶意操作(rm -rf /、反弹 Shell) | 宿主机被攻陷,波及同租户 |
| 数据外泄 | Agent 将用户隐私/企业机密发送到未授权外部 API | 合规违规、业务损失 |
| 凭据滥用 | Agent 窃取或误用 API Key/Token 进行未授权操作 | 资源被窃取、服务中断 |
| 供应链攻击 | Agentpip install恶意包,执行挖矿/后门代码 | 横向移动、持久入侵 |
| 逃逸攻击 | 利用内核漏洞从容器逃逸到宿主机 | 整个集群被攻陷 |
传统容器方案(Docker/Containerd)共享宿主内核——一旦存在内核漏洞,攻击者可直接从容器逃逸到宿主机。对于需要执行不可信代码的 AI Agent 场景,共享内核的隔离模型已不再安全。CubeSandbox 因此采用 KVM MicroVM 作为沙箱隔离底座,为后续网络层的纵深防御提供强隔离前提。
1.2 网络层的五项目标
AI Agent 沙箱的网络层必须解决以下核心问题:
- 隔离性(Isolation):沙箱之间、沙箱与宿主机之间的网络必须完全隔离。
- 可控性(Controllability):精确控制每个沙箱可访问的外部服务(IP/域名/协议)。
- 可观测性(Observability):所有出向流量必须可审计、可追踪。
- 透明性(Transparency):对 Agent 代码零侵入,无需改动应用逻辑。
- 高性能(High Performance):网络策略不能成为千级并发下的瓶颈。
这五项目标决定了架构的选型方向:内核态 eBPF 负责高性能 L4 转发与策略执行,用户态 OpenResty 代理负责需要灵活性的 L7 深度检测。
2. CubeSandbox 网络架构总览
2.1 系统分层架构
CubeSandbox 采用清晰的分层架构,自上而下为:API 网关层、编排调度层、计算节点层、虚拟化层。控制平面(CubeAPI、CubeMaster、CubeOps 等)负责沙箱生命周期管理,数据平面(CubeVS、CubeEgress、CubeProxy)负责流量转发与安全策略执行:
2.2 网络数据平面分工
网络数据面同时覆盖沙箱入向(ingress)与出向(egress)流量。L4 转发与策略执行由内核态 eBPF承担,L7 路由与深度检测由用户态 nginx/openresty承担:
沙箱入向流量(Sandbox Ingress)
- CubeProxy:基于 nginx/openresty 的反向代理,通过 HTTP 头实现高性能路由。
- CubeVS(Ingress):纯内核 eBPF 高性能转发,实现无状态端口映射转换(PortMapping)。
沙箱出向流量(Sandbox Egress)
- CubeVS(Egress):纯内核 eBPF 高性能转发,实现 IP 过滤、域名过滤、SNAT、会话跟踪等沙箱出向能力。
- CubeEgress:基于 nginx/openresty 的 L7 代理,实现 HTTPS 拦截、凭据注入、访问审计等安全能力,可通过 Lua 扩展。
从网络架构图中可以看到宿主机 eth0 的端口分段设计:10000-19999留给内核栈,20000-29999用作 CubeVS Ingress 端口映射段,30000-65535作为 CubeVS SNAT 端口范围——通过端口空间划分将不同数据面路径物理隔开。
2.3 宿主机网络管理(network-agent)
宿主机侧的 network-agent 负责 TAP 设备池管理与分配、PortMapping 端口分配、转发策略数据下发与状态持久化:
- TAP 设备池化:预创建 500+ TAP 设备,沙箱启动时无需再进行 TAP 初始化,将沙箱创建时间减少 59ms 以上。从创建流程图可以看到完整的准备链路:创建 tap 网卡 → 配置地址 → LinkSetUp → LinkSetMTU → 添加 ARP 表项 → 填充 eBPF MapInMap 表 → TAP 设备对 Hypervisor 可用(耗时 60+ms),而 TAP 设备 fd 传递仅约 1ms——预池化将大头开销移到沙箱创建路径之外。
- 策略数据分发:将 CubeVS 与 CubeEgress 的转发策略下发到数据面,使网络流量按用户定义的策略处理。
3. 沙箱网络虚拟化:CubeVS
CubeVS 是 CubeSandbox 网络数据面的内核态核心,源码位于 CubeNet/cubevs,eBPF 数据路径位于 CubeNet/src/mvmtap.bpf.c。
3.1 设计目标
传统容器网络方案(Linux Bridge、OVS、iptables NAT)的每包处理开销会随租户数量增长。CubeVS 用三个小型 eBPF 程序替换整个传统网络栈,实现 ARP 代理、策略执行、L7 代理选择、SNAT、会话创建、反向 NAT、端口映射代理、DNAT 到沙箱 IP、透明代理源 IP 保留等一系列能力:
- 点到点低延迟:每个沙箱独占一个 TAP 设备——无共享网桥、无软件交换跳数、无共享 L2 域,因此无需 ARP 泛洪或 STP。
- 内核态策略执行:网络策略在 eBPF 中执行,CPU 开销极小、性能高。每个 TAP 拥有独立的策略 trie,更新互不影响。
- 可扩展 NAT:SNAT 端口分配采用"锁保护的水位池 + 冲突检测插入",避免 iptables 规则爆炸。
- 安全隔离:TAP 之间天然不可达——通信只能通过 eBPF 程序控制的路径进行。
3.2 网络访问控制一:CIDR 策略 IP 过滤(LPM Trie)
CubeVS 在内核 eBPF 层为每个沙箱实现出向 IP 策略,采用LPM(最长前缀匹配)Trie数据结构进行 CIDR 匹配。按设备隔离的设计意味着更新某个沙箱的策略时,无需遍历或锁住其他沙箱的 map。
评估顺序:allow > deny > default-allow。可配置全量拒绝(0.0.0.0/0)后,再用 allow 规则选择性放行,实现精细控制。
默认策略:CubeVS 默认允许沙箱访问互联网,但阻止访问以下网段,确保沙箱无法触达宿主机内部网络。这些网段可通过allow_out放行,或将allow_internet_access=False设为完全断网(等价于向deny_out添加全量拒绝0.0.0.0/0)。
| CIDR | 说明 |
|---|---|
10.0.0.0/8 | A 类私网 |
127.0.0.0/8 | 回环地址 |
169.254.0.0/16 | 链路本地(沙箱内网网关网段) |
172.16.0.0/12 | B 类私网 |
192.168.0.0/16 | C 类私网 |
这一默认拒绝表在源码中有直接对应实现。在 CubeNet/cubevs/netpolicy.go 中定义了alwaysDeniedSandboxCIDRs常量,与上表完全一致,并通过InstallTAPDefaultDenyPolicy(见 netpolicy.go)在 TAP 创建后安装为不变式默认拒绝条目;buildNetPolicyPlan(见 netpolicy.go)则在AllowInternetAccess=false时向deny_out注入0.0.0.0/0。策略数据存储在allow_out_v3与deny_out两张 LPM Trie 内层 map 中(外层为按 ifindex 索引的 hash-of-maps,见initNetPolicy),每张内层 map 上限maxNetPolicyEntries = 8192条,单条策略的匹配为 O(1) 级别的前缀查找。
3.3 网络访问控制二:DNS 域名策略过滤(LPM Trie)
IP 层策略只能通过 CIDR 匹配目的 IP。而 AI Agent 沙箱的网络访问通常面向域名(如api.openai.com),且单个域名可能解析到多个 IP。CubeVS 通过DNS 策略引擎实现域名级精细控制:
- eBPF 层拦截 DNS 查询(UDP 53 端口),提取被查询域名;
- 若该域名在
allow_out白名单中,则创建域名跟踪记录; - 收到匹配的 DNS 响应后,将响应中的 IP 地址加入
allow_out,放行后续对该域名的流量; - 设置 TTL,确保过期的 IP 会从
allow_out中被回收。
使用约束:
- 域名只能配置在
allow_out白名单中,不能配置在deny_out中; - 若只想放行特定域名流量,建议在
deny_out中配置全量拒绝策略(0.0.0.0/0); - 在
allow_out配置域名时,Cube 会自动将模板配置的 DNS 服务器 IP 加入allow_out; - 限制:该能力依赖沙箱通过 UDP 53 端口的 DNS 查询获取域名 IP——通过配置 hosts 等其他方式无法触发域名放行。
与 L7 策略的协同
DNS 域名过滤策略在内核 eBPF 层提供域名级控制,CubeEgress 则在 L7 提供更精细的控制(http/https、SNI、host、path、method 的精确匹配)。当沙箱网络配置中设置了rules策略时,Cube 会自动将规则中的 host 与 SNI 域名加入allow_out白名单,并将指向这些域名的流量标记为交由 CubeEgress 做 L7 处理(凭据托管、访问审计或 L7 级拒绝)。
- eBPF DNS 策略:快速拒绝已知恶意域名,减少到达 L7 代理的流量;
- CubeEgress L7 策略:支持域名通配符(
*.example.com)、路径前缀(/v1/*)、HTTP 方法等条件匹配。
源码层面,域名匹配的关键实现在 CubeNet/cubevs/dnspolicy.go 的makeDNSAllowRule:将域名反转后编码进 LPM Trie key——精确规则以\0结尾("qq.com"→"moc.qq\0"),通配符规则剥掉*.后以.结尾("*.qq.com"→"moc.qq."),从而让 LPM 查找能"以后缀为前缀"匹配,且*.只匹配子域、不匹配主域本身。DNS 学习结果的 TTL 过期回收由 dns_reaper.go 中的reapDNSLearnedPolicies周期执行;eBPF 侧的 DNS 查询/响应解析与尾调用状态机位于 mvmtap.bpf.c。
4. 沙箱入向网关:CubeProxy
CubeProxy 是沙箱的入向流量网关,负责将外部请求路由到正确的沙箱实例,源码位于 CubeProxy。它基于 OpenResty(Nginx + Lua)构建,采用Host 头路由,支持通配符 DNS(*.sandbox.cube.app),支持 TLS SNI,DNS 配置简单。
Host 格式:{port}-{sandbox_id}.{domain}
Host 解析逻辑在 CubeProxy/lua/rewrite_phase.lua 中实现,例如49983-7c8fbcd45ffe450fb8f7fb223ad45507.cube.app会被拆解为容器端口49983与沙箱实例 ID。CubeProxy 向 Redis 查询该沙箱在宿主机上的 portmapping 信息——即以(container_port, sandbox_id)查得(HostIP, mapping-port),再将请求转发到对应宿主机。后端解析封装在 CubeProxy/lua/sandbox_backend.lua 的resolve_backend中,并带有缓存(cube:v1:shared:sandbox:proxy:{id}元数据键);同时 sandbox_backend.lua 还实现了enforce_traffic_token:对禁止公开访问的沙箱,要求请求携带e2b-traffic-access-token(E2B 兼容)或cube-traffic-access-token匹配令牌,否则返回 403。
5. 应用层安全增强:CubeEgress
CubeEgress 是沙箱的出向安全网关,在 L7 对 HTTP/HTTPS 流量做深度检测。它是 CubeVS 内核策略之上的用户态增强层,解决内核层无法处理的诉求:域名匹配、凭据注入、内容审计等。
核心能力矩阵:
| 能力 | 说明 |
|---|---|
| HTTPS 透明拦截 | MITM 动态证书 + TLS 终结 |
| 域名/路径/方法匹配 | L7 策略引擎,首条命中生效 |
| 凭据注入 | 代理层自动注入,Agent 永不接触凭据 |
| 数据脱敏 | 审计日志中的敏感字段替换 |
| 访问审计 | JSONL 结构化日志 |
| 请求过滤 | 放行或拒绝请求 |
使用限制与 DNS 策略一致:依赖沙箱通过 UDP 53 端口的 DNS 查询获取域名 IP。
CubeEgress 的整体行为与规则语法在 docs/guide/security-proxy.md 中有完整定义(中文版见 docs/zh/guide/security-proxy.md),数据面实现位于 CubeEgress/lua,主配置为 CubeEgress/nginx.conf。
5.1 按需流量调度:eBPF 到 L7 代理的流量分发
并非所有流量都需要 L7 检测。只有命中rules策略中配置了规则的域名的 http/https 流量,才会被 CubeVS按需调度到 CubeDev 设备,进入内核协议栈:
sandbox ──→ cube-dev (host iface) │ ├─ eBPF (mvmtap) 根据 allow_out_v3 将出向 (host, port) 解析为 scheme, │ 并在 SYN 上打上 skb->mark(HTTP 或 HTTPS) │ ├─ iptables mangle/PREROUTING -m mark -j TPROXY │ HTTP mark → 192.168.0.1:8080 (HTTP 监听) │ HTTPS mark → 192.168.0.1:8443 (HTTPS 监听) │ ▼ CubeEgress (OpenResty + lua) │ ├─ ssl_certificate_by_lua → 为请求的 SNI 签发叶子证书 │ (由 CubeEgress 根 CA 签名) │ ├─ access_by_lua → 匹配 L7 规则;allow / deny / inject │ └─ proxy_pass → 原始目的 IP(通过 IP_TRANSPARENT 保留)整个过程结合 iptables TProxy 机制与用户态 socket 的IP_TRANSPARENT选项——stock nginx/openresty 目前不支持该选项,Cube 提供了补丁与预打过补丁的 openresty 容器镜像。补丁源码见 CubeEgress/openresty/0001-nginx-support-TPROXY-listeners-via-transparent-liste.patch:它给listen指令新增transparent关键字,在监听 socket 上启用IP_TRANSPARENT,使内核将目的地址并非本机的数据包投递给该监听;并在 accept 时通过getsockname()捕获真实的 TPROXY 目的地址存入连接池,从而让 nginx 看到真实的原始目的地址而非通配监听地址。启用transparent的监听进程需要CAP_NET_ADMIN/CAP_NET_RAW权限。
由于叶子证书链可对接到沙箱系统信任存储中预置的 CubeEgress 根 CA,工作负载的 TLS 客户端感知不到 MITM,代理便能合法读取并改写请求/响应数据。
5.2 HTTPS 透明拦截:动态证书生成
CubeEgress 通过 MITM(中间人)代理实现 HTTPS 深度检测,核心机制是动态证书生成,实现位于 CubeEgress/lua/cert_signer.lua:
证书架构
- ECDSA P-256:叶子证书使用椭圆曲线——比 RSA 更快、更小;
- 7 天 TTL:短有效期降低泄露影响面(
leaf_ttl_sec = 7 * 24 * 3600,见 CubeEgress/nginx.conf); - 缓存锁:
lua-resty-lock防止同一 SNI 并发生成证书(lua_shared_dict cert_locks 8m配合cert_cache 64m共享字典); - CA 信任注入:模板创建时默认将 Root CA 证书注入沙箱——对 Agent 透明。
5.3 L7 策略引擎
一个沙箱的 CubeEgress 策略可包含多个 rule,每个 rule 由match(匹配条件)与action(动作)组成。规则按顺序匹配,首条命中生效,后续规则跳过;未命中任何规则的请求默认拒绝。
match 语义:
| 字段 | 格式 | 语义 |
|---|---|---|
| sni | *.example.com | 精确匹配或后缀*.通配(仅子域) |
| host | api.example.com | 精确匹配或后缀*.通配(忽略:port) |
| method | {"GET", "POST"} | 数组——任一命中即通过 |
| path | /v1/* | 精确匹配或尾部*前缀匹配 |
| scheme | http/https | 精确匹配 |
请求必须满足所有出现的字段;缺省字段视为通配。match 语法在 docs/guide/security-proxy.md 中还有更细的说明:port与scheme可配对使用以覆盖非标准端口(默认拦截集为{80/http, 443/https},port省略时 allow 规则收紧到默认集、deny 规则则按端口无关匹配整个 host);同一(host, port)的所有规则必须就scheme达成一致,每个 host 最多 8 个不同的(port, scheme)元组;L7 host 必须是域名或单个 IP,子网 CIDR 会被拒绝。
action 执行语义:allow/deny/audit/inject。deny 动作直接从 CubeEgress 返回 HTTP 403,不接触上游——沙箱立即看到拒绝结果,无 DNS 泄漏、无 TCP 握手。
5.4 凭据托管与注入
AI Agent 沙箱不应直接持有 API Key/Token。CubeEgress 的凭据注入机制让沙箱无需携带凭据即可发请求——沙箱外部的 CubeEgress 代理层自动注入:
from cubesandbox import Sandbox, Rule, Match, Action, Inject rules = [ Rule( name="deepseek_api", match=Match(scheme="https", host="api.deepseek.com", method=["POST"], path="/v1/chat", sni="api.deepseek.com"), action=Action( allow=True, audit="metadata", inject=[Inject( header="Authorization", format="Bearer ${SECRET}", secret="sk_xxxxxxxx", # 运维侧持有,沙箱永远看不到 )], ), ), ]凭据注入受多重检查保护,任一检查失败则放弃注入(请求仍可能继续,但不带凭据):
| 检查项 |
|---|
| 请求必须是 HTTPS |
| SNI 匹配规则 |
| Host 头必须匹配 SNI |
| 上游证书验证通过 |
| 策略授权该请求 |
inject仅在action.allow=true时生效(deny 规则带 inject 属于配置错误,注入会被丢弃);format默认值为"${SECRET}",即原始密钥作为完整头值,也可以使用"Bearer ${SECRET}"等任意含${SECRET}占位符的模板。凭据只存在于规则列表中:沙箱创建时推送到 CubeEgress,永不出现在沙箱的环境变量、文件系统或进程空间中。
5.5 访问审计
每个网络请求(无论放行或拒绝)都会生成一条 JSONL(JSON Lines)格式的结构化审计记录。审计日志中的敏感字段从不记录原始值,通过多层脱敏保护:
| 头类型 | 脱敏策略 | 示例 |
|---|---|---|
| Authorization / Proxy-Authorization | 保留 auth scheme,脱敏值 | Bearer <redacted:Bearer> |
| Cookie / Set-Cookie | 保留 cookie 名,脱敏值 | <redacted; names=session_id,theme> |
| X-Api-Key | 全量脱敏 | <redacted> |
| X-Auth-Token / Token | 全量脱敏 | <redacted> |
| 名称含 token/secret/key/password/auth 的头 | 全量脱敏 | <redacted> |
脱敏实现位于 CubeEgress/lua/redactor.lua:精确名小写匹配的黑名单(authorization → 保留 scheme、cookie/set-cookie → 保留 cookie 名、x-api-key/x-auth-token/token → 全量脱敏)加上(?i)(token|secret|key|password|credential|auth)正则兜底。审计日志通过audit动作级别控制:none(不记录)/metadata(默认,记录时间戳、沙箱 IP、目的 IP/端口、scheme、host、method、path、状态码、收发字节数、延迟、TLS 版本与密码套件、上游地址)/full(预留)。日志以 JSONL 落盘在宿主机的/data/log/cube-egress/access.jsonl(见 CubeEgress/nginx.conf),每条请求一行。此外还有两类补充事件:security_event(默认拒绝、规则短路、host/SNI 失配、注入触发等,携带规则名与 reason)与tls_handshake(握手阶段失败,用于区分"TLS 未完成"与"解密后被拒绝")。
5.6 CubeEgress 可扩展性
CubeEgress 是基于 OpenResty 构建的 http/https 透明代理。目前实现了基础请求过滤、凭据托管与访问审计。如果需要更深的检测或其他能力,可以通过修改或新增 Lua 脚本轻松扩展。数据面按 Nginx 阶段拆分在 CubeEgress/lua 目录下,各文件职责清晰:
| 文件 | 挂载阶段 | 职责 |
|---|---|---|
cert_signer.lua | ssl_certificate_by_lua | 为线上 SNI 签发叶子证书 |
bootstrap.lua | init_worker_by_lua(仅 worker 0) | 从 Cubelet 拉取初始策略 |
access_phase.lua | access_by_lua | 对每个请求执行 match → action → inject |
policy.lua | 模块 | 内存策略存储,由admin.lua与bootstrap.lua喂养 |
admin.lua | content_by_lua(默认:9091) | 策略 CRUD 管理 API |
audit.lua | log_by_lua | 逐请求写 JSONL 审计行 |
redactor.lua | 辅助模块 | 对任何用户可见输出清洗密钥 |
规则匹配的校验与冲突检测在 CubeEgress/lua/policy.lua 中完成(如(host, port)的 scheme 冲突检测、inject条目校验、audit级别校验)。CubeEgress 的 TPROXY 监听与 iptables 规则由 CubeEgress/scripts/cube-proxy-iptables-init.sh 及 systemd 单元 CubeEgress/scripts/cube-proxy-net.service 支撑,根 CA 生成脚本见 CubeEgress/gen-ca.sh。
5.7 需要了解的不走 CubeEgress 的边界场景
以下场景会完全绕过 CubeEgress,值得运维注意:
- 内部
cube-dev流量:沙箱到沙箱、以及到集群内服务(如 Cube API)的流量不进入 TPROXY 链,规则不生效; - L7 规则未覆盖的 TCP/UDP:TPROXY 链只重定向 L7 规则标记的流量(默认
{80/http, 443/https}集加上规则声明的自定义(port, scheme))。规则未覆盖端口的直连 TCP 仍受 L3/L4 的allow_out/deny_out策略约束,但对 CubeEgress 不可见; - 未烘焙 CA 的模板:若模板以
--with-cube-ca=false创建,沙箱 TLS 客户端不信任 CubeEgress 叶子证书,HTTPS 调用会在任何规则生效前就因自签证书报错失败。
6. 总结
CubeSandbox 的网络体系通过"eBPF 内核态 + OpenResty 用户态"组合实现高性能转发;通过资源本地化分配、规范化沙箱配置与资源池化,实现极致的沙箱创建速度。在 AI Agent 安全沙箱这一新兴场景下,它带来了多项技术创新:
| 创新点 | 传统方案 | CubeSandbox 方案 | 优势 |
|---|---|---|---|
| 网络隔离 | Linux Bridge + iptables | 点对点 TAP + eBPF | 零广播开销,内核态执行 |
| 策略执行 | iptables 规则链 | LPM Trie + eBPF | O(1) 查找,按沙箱隔离 |
| 域名过滤 | 应用层代理 | 内核态 eBPF | 高性能转发 |
| HTTPS 检测 | 手工配置证书 | 动态证书生成(ECDSA P-256) | 零预配置,自动管理 |
| 凭据管理 | 环境变量/配置文件 | 代理层注入 + 多重校验 | Agent 沙箱永不接触凭据 |
| 审计日志 | 文本格式,需解析 | JSONL 结构化 + 自动脱敏 | 合规友好,可直接分析 |
从安全纵深的角度看,这套体系呈现清晰的分层防线:KVM MicroVM 隔离阻断容器逃逸路径 → eBPF 内核数据面提供高性能 L4 过滤与域名级放行 → L7 代理对命中规则的流量做解密后的细粒度控制与凭据托管 → JSONL 审计日志对全部出向流量留痕并自动脱敏。各层职责单一、接口清晰,既保证了千级并发下的转发性能,也保证了"开放执行"与"安全可控"在 AI Agent 场景下的可同时成立。
【免费下载链接】CubeSandboxInstant, Concurrent, Secure & Lightweight Sandbox for AI Agents.项目地址: https://gitcode.com/GitHub_Trending/cu/CubeSandbox
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考