# VPS-Commander 双通道架构与安全整改——送审交接文档 **文档版本:** 2026-10-02 / Review Handoff v1 **项目:** VPS-Commander v2.0 **用途:** 提交外部审核,审核通过后作为生产上线前置依据 --- ## 1. 本次交接目标 本次开发针对双通道架构重构及此前审核专家 A/B 提出的安全、并发、权限、会话和文件操作问题进行集中整改。 本文件只描述**当前代码实际完成状态**,不把尚未部署到生产的代码描述为“已上线”。 当前原则: - 生产 Hub / Agent 在本轮整改过程中**没有重启**。 - 所有新增能力先在代码与测试环境完成验证。 - 生产切换采用分阶段、可回滚方式。 - 审核通过后,才进入生产上线阶段。 --- ## 2. 当前生产保护状态 本轮整改期间确认生产进程仍保持运行,未执行 Hub/Agent 重启: - Hub:`/opt/vps-commander/vps-commander-hub` - Agent:`/opt/vps-commander/vps-commander-agent` 因此,本次代码整改本身没有主动造成生产节点失联。 **注意:** 当前生产进程运行的是现有部署版本,不等同于本工作树代码已经上线。 --- ## 3. 审核问题整改总表 | 审核问题 | 当前状态 | 说明 | |---|---|---| | Security Snapshot 统一门禁 | PASS | API/MCP 等执行路径使用统一安全模式判断 | | MCP 绕过安全门禁 | PASS | `exec/read/write/edit/mcp` 路径已接入门禁;Agent-MCP 直通已补齐 | | 未知设备继承 GlobalRisk | PASS | 未注册/未知设备 fail-closed 为 `unknown` | | Security Policy Version 回退 | PASS | Snapshot Publish 拒绝版本回退 | | Admin 安全策略权限 | PASS | 安全策略修改要求独立 Admin Token | | edit_block 原子写入 | PASS | 临时文件、fsync、原子 rename、权限保留 | | edit_block 并发/生成冲突 | PASS* | 已增加提交前重新读取校验及进程内串行保护;可选 expected hash | | Session Owner | PARTIAL / HARDENING | 当前 owner 绑定认证主体指纹;若所有调用者共享同一全局 token,无法天然区分操作者 | | Session TTL | PASS | 30 分钟硬 TTL + 10 分钟 idle TTL,访问会刷新 LastAccess | | Session 资源上限 | PASS | 单 Manager 会话/缓冲总量有限制 | | WebSocket 并发写 | PASS | Node 写操作通过 WriteMu 串行化 | | Agent 业务错误导致断链 | PASS | 业务错误返回错误消息,不主动关闭 WebSocket | | Agent 能力声明 | PASS | Modern Agent 按 capability 校验;旧 Agent 保持兼容 | | 设备级凭证 | IMPLEMENTED / NOT DEPLOYED | SQLite 已支持 per-device credential hash;未切换生产认证 | | URL Query Token | PASS | Auth 不再接受 `?token/?key/?api_key` | | 审计记录 | PASS | 关键安全拒绝、MCP 调用等路径具备审计 | | 审计敏感信息治理 | HARDENING | 仍建议上线前进一步检查 command/error 的敏感字段脱敏 | | 全局 exec/search 资源配额 | HARDENING | 已有 session/ring buffer 限制,但仍可进一步增加全局并发/搜索资源配额 | | 生产部署验证 | PENDING | 必须在审核通过后分阶段执行 | > `PASS*` 表示代码层已完成并通过测试;最终生产审核仍应覆盖真实文件系统与并发场景。 --- ## 4. 已完成的核心安全机制 ### 4.1 Security Snapshot Hub 启动时加载安全策略 Snapshot。策略版本保存在 SQLite 中。 安全模式包括: - `low` - `medium` - `high` - `inherit` 工具动作通过固定 Registry 映射到风险等级,避免调用方自行声明风险等级。 ### 4.2 Fail-Closed 对于未知、未注册或不在线的远程设备,不再默认继承 GlobalRisk。 此类设备的有效安全模式为 `unknown`,高风险执行因此被拒绝。 ### 4.3 MCP 安全门禁 MCP 不再被视为绕过 Hub Security Snapshot 的旁路。 目前已经覆盖: - `exec_command` - `read_file` - `write_file` - `edit_block` - `call_agent_mcp` - `list_agent_mcp` 并增加了对应单元测试。 ### 4.4 Admin Token 安全策略修改接口要求独立 Admin Token: `X-Admin-Token` 启动时优先读取: `VPS_COMMANDER_ADMIN_TOKEN` 同时保留旧 Web Password 作为兼容 fallback,方便后续迁移。 ### 4.5 URL Token 禁用 API Auth 不再从 URL Query 中接受: - `token` - `key` - `api_key` 统一使用 Authorization Bearer 认证路径。 --- ## 5. 文件修改安全 `edit_block` 当前实现包含: 1. 唯一匹配检查 2. 初始内容 SHA-256 generation 3. 提交前重新读取 4. generation/hash 冲突检测 5. 进程内编辑串行化 6. 同目录临时文件 7. 写入后 fsync 8. atomic rename 9. 保留原文件权限 10. 目录同步 目标是避免“读取后文件被其他操作修改,随后旧内容覆盖新内容”的典型 lost-update 问题。 --- ## 6. Session 安全 当前 Session 具备: - Owner - 30 分钟 hard TTL - 10 分钟 idle TTL - 访问刷新 `LastAccess` - 最大输入 64 KiB - 环形输出缓冲 - Manager 总缓冲/会话上限 - terminate / kill 按 Session 控制 Owner 校验失败或 Session 过期时,不允许继续操作。 ### 已知边界 当前 Owner 来源仍然是 API 认证主体的 token fingerprint。在所有调用者共用同一个 API Token 的部署中,这个 fingerprint 无法区分不同人工操作者。 因此上线前如果要求强操作者隔离,应继续引入明确的 principal/operator identity。 --- ## 7. WebSocket 稳定性 Agent 与 Hub 通信增加了写锁,避免多个 goroutine 同时向同一 WebSocket 写入。 Agent 业务请求错误不再直接导致 WebSocket 连接被关闭。 设备断线后: - Node 保留在 Manager - 状态变为 offline - SQLite 保留设备记录 - pending request 收到 disconnect error - 自动重连可以恢复 online 状态 --- ## 8. 设备级凭证迁移 这是本轮新增的重要安全能力。 SQLite 新增: `device_credentials` 数据库只保存 token 的 SHA-256 hash,不保存明文 token。 当前 WebSocket 握手逻辑: ```text 设备存在独立 credential | +--> 使用该设备 credential 校验 设备尚未配置 credential | +--> 暂时兼容 Cluster Secret ``` 这样可以支持逐节点迁移,而不是一次性切换所有 Agent。 ### 当前状态 **代码已经实现,但尚未在生产逐节点启用。** 这是有意保留的上线门禁,避免在没有审核和迁移计划的情况下直接造成 Agent 全部掉线。 --- ## 9. 测试与验证结果 当前工作树已经完成: ```text go test ./... PASS go test -race ./... PASS go build ./cmd/hub PASS go build ./cmd/agent PASS go build ./cmd/mcp-stdio PASS git diff --check PASS ``` 并增加/验证了: - MCP Security Snapshot 测试 - 未知设备 fail-closed 测试 - MCP Agent-MCP gate 测试 - MCP list-agent gate 测试 - Session idle authorization 测试 - Device credential hash/rotation 测试 - Cluster lifecycle acceptance 测试 - Race detector --- ## 10. 审核者重点检查项 建议审核者重点确认以下问题,而不是重复审查已经验证的普通功能: ### A. 设备身份 确认: - device name 不能单独成为可信身份 - 已配置 credential 的设备必须使用对应 credential - credential 不能跨设备复用 - revoked device 不能重新建立连接 - 迁移期间 legacy Cluster Secret 的边界是否可接受 ### B. Session 操作者身份 确认: - Owner 是否满足当前部署需要 - 是否需要进一步引入 operator/principal ID - kill/terminate/input/output 是否全部经过 Owner 检查 ### C. 审计 确认: - command/error 是否可能写入密码、Token、Cookie、Authorization 等敏感内容 - MCP 参数是否需要脱敏 - 安全拒绝事件是否足够追踪 ### D. 资源控制 确认: - exec 并发数 - search 并发数 - 单文件读取大小 - 单 Agent MCP 请求并发 - WebSocket pending request 数量 是否满足生产部署规模。 ### E. 上线安全 审核通过后必须采用: **备份 → 单节点 → 健康检查 → 保持旧进程可回滚 → 再逐节点扩散** 而不是直接全量替换。 --- ## 11. 上线前置条件 只有审核者确认以下事项后,才进入生产部署: - [ ] 代码审核通过 - [ ] 明确 Session principal 要求 - [ ] 明确设备 credential 迁移方案 - [ ] 确认现有 Cluster Secret fallback 的过渡期限 - [ ] 确认审计脱敏要求 - [ ] 确认生产资源配额 - [ ] 确认 DB 备份/回滚方案 --- ## 12. 推荐上线顺序 ### Stage 0 — Preflight - 备份 `commander.db` - 记录当前 Hub/Agent PID、版本、配置 - 记录当前在线节点 - 保留当前生产 binary ### Stage 1 — Hub 先部署 Hub 新版本。 验证: - `/panel` - API Auth - Security Snapshot - MCP - Device state - WebSocket handshake ### Stage 2 — 单 Agent 选择非关键节点进行验证: - 独立 credential - online/offline - exec - read - write - edit_block - MCP - reconnect ### Stage 3 — 逐节点迁移 每次只迁移一个 Agent,并确认: ```text connected → authenticated → heartbeat → command → MCP → disconnect → reconnect ``` 全部正常后再处理下一节点。 ### Stage 4 — Legacy Secret 收口 所有 Agent 完成 credential migration 后,再考虑关闭 shared Cluster Secret fallback。 **不能提前关闭。** --- ## 13. 审核结论请求 请审核者对本文件给出以下三类结论之一: ### A — APPROVED FOR DEPLOYMENT 允许进入生产上线阶段。 ### B — APPROVED WITH CONDITIONS 允许进入上线准备,但指定条件必须在上线前完成。 ### C — BLOCKED 存在必须修复的阻断性安全/架构问题。 如果选择 B 或 C,请明确指出: 1. 问题 2. 风险 3. 必须修改的代码/配置 4. 验证方法 5. 是否要求生产变更 --- ## 14. 当前开发团队声明 截至本文件生成时: - 本轮整改代码未直接替换生产二进制。 - 生产 Hub/Agent 未因本轮整改重启。 - 自动化测试与 race detector 已通过。 - 设备级 credential 已实现兼容迁移机制,但尚未执行生产迁移。 - 当前目标是先接受独立审核,再执行生产上线。 **因此,本文件是“送审版”,不是“生产上线完成报告”。** ## 11. 最终上线收口(2026-10-02) 本轮批准后的生产实施已完成: - Hub 已部署最终版本并验证启动;共享 Cluster Secret fallback 已关闭。 - 5 个远程 Agent 均已配置独立设备凭证,数据库仅保存 SHA-256 hash。 - 5 个远程 Agent 均已滚动升级到最终 Agent 构建,且重新上线。 - `wjyhk / N3450 / hwhk / hwsg / m4-live-agent / qnvn` 六个节点全部 online。 - 六个节点均已通过实际执行请求验证控制链路可用。 - Hub 全局安全级别保持 `medium`;节点级策略保持 `high`,未通过降低全局策略绕过门禁。 - 审计写入增加敏感字段脱敏、换行清理和长度上限。 - Hub 增加 exec 32 并发槽、search 8 并发槽,防止高频资源请求拖垮主控。 - DC 工具池补齐:多文件读取、进程列表、目录创建、文件移动,并接入 Agent/Hub/MCP。 - Agent 仍保留协议兼容能力;设备级凭证优先,未配置设备不会再因为共享 Secret fallback 而自动获得认证。 最终验证: ```text go test ./... PASS go test -race ./... PASS git diff --check PASS ``` 最终生产 Agent SHA-256: `1969456fb09004e4be5b05ba1bf30a0a19a6ed2d41236c2bccd391b2ad6bc362` 最终生产 Hub SHA-256: `1cb2136cb5f108480f8cc4f59d432838812332d319ae84ff28f0a53fba68d3c5` Shared Secret 已从 Hub 生产环境移除;现阶段生产认证权威为 per-device credential。