# Box 系统 toB 商业化分析 > 更新日期: 2026-06-02 > 状态更新: 自部署社区版已具备发布条件(box 可选、降级完善、无迁移欠债);工具调用循环上限、配额遍历异步化、`host_path` 挂载白名单等已落地。剩余多租户 / 安全硬化项见 [SaaS 阻塞项清单](./box-issues.md)。 > 分支: `feat/sandbox` (LangBot + langbot-plugin-sdk) --- ## 1. 现有优势 | 能力 | toB 价值 | 代码位置 | |------|---------|---------| | **沙箱隔离执行** | 企业安全运行不受信代码的基础能力 | SDK `box/backend.py` | | **多后端支持** | 适配不同企业容器基础设施 (Podman/Docker/nsjail/E2B) | SDK `box/runtime.py` `_select_backend()` | | **E2B 云沙箱** | SaaS / 无 Docker 部署的兜底执行环境 | SDK `box/e2b_backend.py` | | **连接自愈** | 心跳 + 自动重连,单点 Box runtime 故障可恢复 | `pkg/box/connector.py` `_heartbeat_loop`, `pkg/box/service.py` `_reconnect_loop` | | **Profile + locked 字段** | 运维锁定安全边界,LLM/用户无法绕过 | `pkg/box/service.py`, SDK `box/models.py` | | **资源限制** | CPU/内存/PID 数限制防止资源滥用 | SDK `backend.py` `--cpus/--memory/--pids-limit` | | **Workspace quota** | 磁盘用量控制 | `pkg/box/service.py` `_enforce_workspace_quota` | | **静默降级** | Box 不可用不影响其他功能,降低部署门槛 | `pkg/box/service.py:78` `_available=False` | | **孤儿容器清理** | 防止泄漏的容器持续占用资源 | SDK `backend.py` `cleanup_orphaned_containers` | | **网络隔离** | `--network none` 防止数据外泄 | SDK `backend.py` start_session | | **只读根文件系统** | `--read-only` 防止容器被持久篡改 | SDK `backend.py` start_session | | **Host path 白名单** | `allowed_host_mount_roots` 限制可挂载目录 | `pkg/box/service.py` `_validate_host_mount` | --- ## 2. toB 差距分析 ### 2.1 安全与合规 | 维度 | 现状 | toB 要求 | 优先级 | |------|------|---------|--------| | **WS relay 认证** | 无认证,任何人可 attach | 至少 token 认证 | **P0** | | **安全策略** | policy.py 是死代码,实际无细粒度控制 | 工具级 allow/deny、沙箱模式控制 | **P0** | | **审计日志** | 仅内存中 50 条 `_recent_errors` | 持久化审计:谁何时执行了什么、结果如何 | **P0** | | **Host path 校验** | 黑名单策略,`/` 未拦截 | 白名单策略,默认拒绝 | **P1** | | **数据驻留** | 无控制 | GDPR / 等保要求的数据隔离 | **P2** | ### 2.2 多租户 | 维度 | 现状 | toB 要求 | 优先级 | |------|------|---------|--------| | **租户隔离** | 无租户概念 | BoxSpec/Profile 绑定 tenant_id | **P0** | | **RBAC** | 仅 token 认证 | admin/operator/viewer 角色权限 | **P0** | | **资源配额** | 单一 workspace quota | 每租户 CPU 时间/内存/并发/执行次数配额 | **P1** | | **Session 隔离** | 所有 session 共享 dict | 按租户分区,互不可见 | **P1** | ### 2.3 可靠性 | 维度 | 现状 | toB 要求 | 优先级 | |------|------|---------|--------| | **连接恢复** | 已实现:20s 心跳 + `_reconnect_loop` 指数退避 | 已满足基本要求 | 已有 | | **Session 清理** | 机会性(仅新建时触发) | 定时清理 + 独立 reaper | **P1** | | **水平扩展** | 单 Box Runtime 实例 | 多实例负载均衡(按 tenant 路由) | **P1** | | **优雅降级** | 已有(_available=False) | 已满足基本要求 | 已有 | | **Backend 自愈** | 已实现:`get_status` 时若 backend 不可用会重新选择 | 已满足基本要求 | 已有 | ### 2.4 可观测性 | 维度 | 现状 | toB 要求 | 优先级 | |------|------|---------|--------| | **监控指标** | 无 Prometheus metrics | session 数/执行延迟/资源用量/错误率 | **P1** | | **结构化日志** | Python logging, 无结构化 | JSON 格式日志,含 trace_id/tenant_id | **P1** | | **前端面板** | 监控页接入 `/api/v1/box/status`(backend 名 + 活跃 session 数);`sessions` / `errors` 仍未接入 | 完整状态面板 + 历史错误/审计列表 | **P2** | --- ## 3. SaaS 部署架构建议 ### 3.1 方案 A: 共享 Box Runtime Pool (快速上线) ``` LangBot Instance ──> Box Runtime (共享) ├─ tenant_id 标签隔离 ├─ Redis 配额计数器 └─ Container labels: langbot.tenant_id=xxx ``` - **优点**: 改动最小,加 tenant_id 到 BoxSpec/labels 即可 - **缺点**: 容器引擎共享,安全隔离弱 ### 3.2 方案 B: 每租户 K8s Namespace + gVisor (推荐中期) ``` LangBot ──> K8s API ├─ namespace: tenant-xxx │ ├─ RuntimeClass: gVisor (runsc) │ ├─ ResourceQuota │ └─ NetworkPolicy └─ namespace: tenant-yyy └─ ... ``` - **优点**: 强隔离(namespace + gVisor),原生 K8s 配额 - **缺点**: 需要重写 backend 为 K8s Job,部署复杂度高 ### 3.3 方案 C: K8s Job 直接编排 (长期) ``` LangBot ──> K8s Job per execution ├─ 每次执行创建 Job ├─ Pod Security Standards ├─ 自动调度和资源分配 └─ Job TTL Controller 自动清理 ``` - **优点**: 最强隔离,天然水平扩展 - **缺点**: 冷启动延迟,架构重写 **推荐演进路径**: A → B → C --- ## 4. 配额体系建议 ### 三层配额 | 层 | 实现 | 作用 | |----|------|------| | **内核层** | Docker `--cpus`/`--memory`/`--storage-opt` | 硬性资源上限,不可绕过 | | **应用层** | Redis 原子计数器 | 并发 session 数/执行次数/CPU 时间预算 | | **计费层** | 月度聚合 | 按租户计费(session-hours/execution-count) | ### Profile 与套餐映射 | 套餐 | Profile | locked 字段 | 配额 | |------|---------|------------|------| | Free | `offline_readonly` | network, host_path_mode, rootfs | 10 exec/天, 0.5 CPU, 256MB | | Pro | `default` | (无) | 100 exec/天, 1 CPU, 512MB | | Enterprise | `network_extended` | (按需) | 无限, 2 CPU, 1GB, 自定义镜像 | ### TOCTOU 配额修复 当前 `_enforce_workspace_quota` 的 TOCTOU 问题可通过两种方式解决: 1. **预留式配额** (应用层): Redis `INCRBY` 预扣额度 → 执行 → 成功则扣减,失败则回滚 2. **内核级限制** (Docker): `--storage-opt size=500m` 直接限制容器可写层大小 --- ## 5. 优先实施路线 ### Phase 1 (2-4 周): 安全基线 - [ ] WS relay 加 token 认证 - [ ] 接入或删除 policy.py - [x] ~~Box 加重连和心跳~~(已完成,见 [box-issues.md 已解决](./box-issues.md)) - [ ] 审计日志持久化(至少写文件/数据库) - [ ] `security.py` 加 `/` 拦截,考虑白名单 - [ ] INIT 与 backend 初始化顺序整理(避免 backend 在配置到达前实例化) ### Phase 2 (4-8 周): 多租户基础 - [ ] BoxSpec 加 `tenant_id` 字段 - [ ] 容器 labels 加 tenant 标识 - [ ] Redis 配额计数器(并发/执行次数/时间) - [ ] RBAC 基础框架 - [ ] 定时 session reaper ### Phase 3 (8-16 周): 生产就绪 - [ ] Prometheus metrics exporter - [ ] 前端 Box 状态面板 - [ ] K8s backend 支持 (方案 B) - [ ] 结构化日志 (JSON, trace_id) - [ ] 水平扩展支持