This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
# WxAgent 远程协议草案 v1.0
|
||||
|
||||
> 对应:[`WxAgent-远程多节点控制与白名单数据上报开发计划.md`](./WxAgent-远程多节点控制与白名单数据上报开发计划.md)
|
||||
> 状态:本地闭环已冻结;生产 TLS、节点 Token 签发和数据保留策略需在部署环境配置。
|
||||
> 状态:本地闭环已冻结;生产 TLS/mTLS 证书、外部 Secret、撤销文件、备份和保留策略需在部署环境配置。
|
||||
|
||||
## 1. 传输和认证
|
||||
|
||||
- 协议版本:`v1`。
|
||||
- 节点只主动向控制面发起 HTTP 请求;生产地址必须使用 HTTPS。HTTP 仅允许 `127.0.0.1`/`::1` 本地集成验证。
|
||||
- 节点只主动向控制面发起 HTTP 请求;生产地址必须使用 HTTPS,节点可要求 mTLS 客户端证书。HTTP 仅允许显式配置的私有网络验证或 `127.0.0.1`/`::1` 本地集成验证。
|
||||
- 节点请求使用 `Authorization: Bearer <node-token>`。Token 按节点签发、可撤销,不写入日志和控制面持久化文件。
|
||||
- Web 用户先调用 `POST /v1/auth/login`,使用返回的短期 Bearer 会话访问管理 API。未认证的业务请求返回 `401`。
|
||||
- 每个请求可携带 `X-Correlation-Id`;服务端响应同名响应头和 JSON `correlation_id`。
|
||||
|
||||
@@ -348,7 +348,7 @@ UIA 事件/本地读取/任务结果/诊断
|
||||
Agent 只有在同时配置并成功验证以下两项后,才允许连接中心、消费远程任务或上报白名单数据:
|
||||
|
||||
- `authAddress`:中心认证/接入地址,必须使用 HTTPS 或等价安全传输。
|
||||
- `token`:节点专用认证 Token,按节点单独签发,可撤销、可轮换。
|
||||
- `token`:节点专用认证 Token,按节点单独签发;本项目不实现 Token 轮换,泄露时通过外部配置禁用对应节点并重启控制面。
|
||||
|
||||
示例:
|
||||
|
||||
@@ -559,6 +559,6 @@ Agent 只有在同时配置并成功验证以下两项后,才允许连接中
|
||||
- 已实现多节点配置入口:控制面支持 `WXAGENT_NODE_TOKENS` JSON map;单节点环境变量仍兼容。节点 `service.json` 可通过 `remoteConfigurationFile` 使用 CLI 维护的远程配置。
|
||||
- 已实现消息事件的稳定会话标识要求:监听器只能在唯一 AutomationId 可确认时生成远程事件;本地事件总线不缓存消息正文,非白名单正文不入队、不持久化、不发送。
|
||||
- 已补充远程只读查询任务:`POST /v1/reads/sessions`、`POST /v1/reads/contacts`、`POST /v1/reads/messages`;结果沿用任务租约/状态/幂等模型,节点读取前按本地已验证白名单过滤,消息查询仅返回当前 UI 可见历史。
|
||||
- 自动化证据:`npm run build --prefix control-plane/web`;`cd control-plane && go test ./... && go vet ./...`;Core 测试 166/166、Service 测试 20/20;`dotnet build WxAgent.sln -c Release -p:EnableWindowsTargeting=true`;`scripts/remote-control-smoke.sh` 均通过。
|
||||
- 自动化证据:`npm run build --prefix control-plane/web`;`cd control-plane && go test ./... && go vet ./...`;Core 测试 168/168、Service 测试 20/20;`dotnet build WxAgent.sln -c Release -p:EnableWindowsTargeting=true`;`scripts/remote-control-smoke.sh` 均通过。
|
||||
- 真机 `windows-direct-20260911` 已在已登录、未锁定会话中注册并保持 `Online`;`send-text` 任务已完成 `Pending → Running → Succeeded`,并通过文件传输助手本地历史读回唯一标记确认。远程读取已验证会话 1 条、私聊联系人 1 条、群 1 条、消息 3 条,四个读取任务均为 `Succeeded`。
|
||||
- 当前不能标记为生产 R5 完成:控制面仍是单进程 JSON 文件/HTTP MVP,生产 HTTPS/mTLS、Token/证书撤销与轮换、外部密钥管理、规模压测、备份恢复和完整保留策略仍待完成。`/api/v1/sessions/open` 的导航能力仍可能返回 `CapabilityDisabled`;远程消息历史不是数据库全量历史。详细部署步骤见 [`WxAgent-远程控制面架构与部署说明-v1.0.md`](./WxAgent-远程控制面架构与部署说明-v1.0.md)。
|
||||
- 当前不能标记为生产 R5 完成:控制面已支持直接 TLS、节点 mTLS、客户端证书撤销文件、外部 Secret 文件、自动备份/保留、active/passive 数据锁和就绪检查;生产仍待完成外部 Secret/证书接入演练、异地备份恢复、规模压测和故障演练。本项目不实现 Token 轮换;泄露时由外部配置禁用对应节点并重启控制面。`/api/v1/sessions/open` 的导航能力仍可能返回 `CapabilityDisabled`;远程消息历史不是数据库全量历史。详细部署步骤见 [`WxAgent-远程控制面架构与部署说明-v1.0.md`](./WxAgent-远程控制面架构与部署说明-v1.0.md)。
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
- 远程读取可见会话、联系人/群和当前 UI 可见消息历史;
|
||||
- 节点本地白名单过滤、稳定身份校验、结果范围化保存和断线补传;
|
||||
- React 管理页面登录、节点/任务/事件/审计查询;
|
||||
- Gitea Actions 构建并推送控制面容器镜像。
|
||||
- Gitea Actions 构建并推送控制面容器镜像;
|
||||
- 直接 TLS、节点 mTLS、客户端证书指纹撤销文件和外部 `*_FILE` Secret 注入;
|
||||
- 数据文件 active/passive 单写锁、自动备份、保留期限和 `/readyz` 就绪检查;
|
||||
- 有界的就绪/只读任务并发基线脚本。
|
||||
|
||||
当前明确不提供:
|
||||
|
||||
@@ -25,7 +28,7 @@
|
||||
- 控制面直接修改节点白名单;
|
||||
- 非白名单会话、完整微信数据库或数据库密钥上传;
|
||||
- 远程全量数据库历史读取;消息读取只来自当前微信 UI 可见历史;
|
||||
- 生产级 HTTPS/mTLS 终止、在线 Token 撤销/轮换、HA 和规模压测;
|
||||
- active-active 多实例、跨节点复制和托管式 Secret/PKI 服务;
|
||||
- `/api/v1/sessions/open` 的远程导航能力。当前该接口可能返回 `409 CapabilityDisabled`,不影响只读任务接口。
|
||||
|
||||
## 2. 总体架构
|
||||
@@ -158,6 +161,7 @@ Pending → Accepted → Running → Succeeded
|
||||
| 心跳超时 | 45 秒 | Web 查询节点时标记 `Offline` |
|
||||
| Web 会话 | 8 小时 | 控制面内存会话 |
|
||||
| 任务轮询窗口 | 0–30 秒 | `wait_seconds` |
|
||||
| 备份间隔 | 5 分钟 | `WXAGENT_CONTROL_PLANE_BACKUP_INTERVAL` |
|
||||
| 事件正文 | 16 KiB | 节点协议上限 |
|
||||
| 任务载荷 | 64 KiB | 节点/中心共同限制 |
|
||||
| 任务结果 | 512 KiB | 含读取内容 |
|
||||
@@ -299,9 +303,11 @@ POST /v1/nodes/{node_id}/events
|
||||
|
||||
```text
|
||||
/data/control-plane-data.json
|
||||
/data/control-plane-data.json.lock
|
||||
/data/backups/control-plane-data.json.<unix-ns>.json
|
||||
```
|
||||
|
||||
`Store` 在单进程 Mutex 下执行读写,写入临时文件、`Sync` 后原子替换,文件权限为 `0600`。持久化对象包括:
|
||||
`Store` 在进程内 Mutex 和数据文件旁的非阻塞 flock 下执行读写;同一数据卷同时只允许一个活动控制面实例。写入临时文件、`Sync` 后原子替换,并在替换父目录后同步目录,文件权限为 `0600`。按 `BackupInterval`(默认 5 分钟)把旧版本写入备份目录并按 `BackupCount` 删除旧备份;任务、事件和审计按配置的保留时长在下一次写入前清理,运行中任务不会被清理。持久化对象包括:
|
||||
|
||||
```text
|
||||
PersistedState
|
||||
@@ -311,7 +317,7 @@ PersistedState
|
||||
└── audit 登录、任务和节点操作审计
|
||||
```
|
||||
|
||||
当前没有数据库事务、跨实例锁、自动 TTL、异地备份或 HA。升级/重建容器前必须备份 `/data/control-plane-data.json`,恢复时保持文件权限并确保只有一个控制面实例挂载该数据文件。
|
||||
当前没有数据库事务或 active-active HA;flock 提供的是共享卷上的 active/passive 单写保护。自动备份和按时长保留已实现,但异地复制、恢复演练和备份监控仍是部署门禁。升级/重建容器前应使用 `scripts/control-plane-data.sh backup`,恢复前停止活动实例并使用 `restore`,恢复时保持文件权限并确保只有一个控制面实例挂载该数据文件。
|
||||
|
||||
### 6.2 Windows 节点
|
||||
|
||||
@@ -446,15 +452,17 @@ docker run -d \
|
||||
curl --fail http://10.1.1.104:18090/healthz
|
||||
```
|
||||
|
||||
更推荐使用 Compose、systemd 或编排平台的 Secret 注入功能,避免 Token 出现在 `docker inspect` 的长期配置、进程列表和 shell 历史中。当前镜像支持环境变量认证,但尚未内置外部 Secret Provider。
|
||||
更推荐使用 Compose、systemd 或编排平台的 Secret 注入功能,避免 Token 出现在 `docker inspect` 的长期配置、进程列表和 shell 历史中。当前镜像支持 `*_FILE` Secret 文件注入;Secret 文件本身仍由部署平台负责保护和挂载。
|
||||
|
||||
单节点兼容环境变量也可用:
|
||||
单节点兼容环境变量也可用;对应的 `*_FILE` 形式优先从文件读取:
|
||||
|
||||
```text
|
||||
WXAGENT_NODE_ID
|
||||
WXAGENT_NODE_TOKEN
|
||||
WXAGENT_NODE_TOKEN / WXAGENT_NODE_TOKEN_FILE
|
||||
WXAGENT_WEB_USER
|
||||
WXAGENT_WEB_PASSWORD
|
||||
WXAGENT_WEB_PASSWORD / WXAGENT_WEB_PASSWORD_FILE
|
||||
WXAGENT_NODE_TOKENS / WXAGENT_NODE_TOKENS_FILE
|
||||
WXAGENT_WEB_USERS / WXAGENT_WEB_USERS_FILE
|
||||
```
|
||||
|
||||
多节点/多 Web 用户使用 JSON map:
|
||||
@@ -464,17 +472,18 @@ WXAGENT_NODE_TOKENS={"node-a":"token-a","node-b":"token-b"}
|
||||
WXAGENT_WEB_USERS={"admin":"password-a","auditor":"password-b"}
|
||||
```
|
||||
|
||||
### 8.3 生产 HTTPS/mTLS 门禁
|
||||
### 8.3 生产 HTTPS/mTLS
|
||||
|
||||
当前 Go 进程直接提供 HTTP。生产不得把该 HTTP 端口直接暴露到公网;正式部署至少应:
|
||||
当前 Go 进程支持直接 TLS。生产不得把明文端口直接暴露到公网;正式部署至少应:
|
||||
|
||||
1. 在受控入口终止 HTTPS,并配置可信证书、强 TLS 和安全 Header;
|
||||
2. 节点到入口使用 HTTPS;
|
||||
3. 按节点管理、轮换和撤销 Token,或在边界与节点接入层启用 mTLS;
|
||||
4. Token/密码放入外部密钥管理,不进入容器环境快照和日志;
|
||||
5. 仅允许管理端、节点网段访问对应路径;
|
||||
6. 对 `/data` 做加密备份、恢复演练和保留策略;
|
||||
7. 完成失效证书、重放、中心重启、节点断线和并发规模测试。
|
||||
1. 配置 TLS 证书和私钥,服务端最低 TLS 1.3;
|
||||
2. 配置签发节点证书的客户端 CA,并启用 `WXAGENT_MTLS_REQUIRE_NODE_CERT=true`;Web 管理用户仍可只使用 HTTPS;
|
||||
3. 节点使用 PEM 客户端证书和私钥,服务端按 CA 验证;
|
||||
4. 将已泄露或失效的客户端证书 DER-SHA256 指纹逐行写入撤销文件。可用 `scripts/revoke-client-certificate.sh` 原子追加;控制面每次节点认证重新读取该文件,撤销文件缺失/不可读时启动或认证失败。Docker Secret 更新后需重建控制面容器;
|
||||
5. Token 和密码通过 `WXAGENT_NODE_TOKENS_FILE`、`WXAGENT_WEB_USERS_FILE` 等外部 Secret 文件注入,不进入镜像和控制面数据文件;本项目不实现 Token 轮换;
|
||||
6. 仅允许管理端、节点网段访问对应路径;
|
||||
7. 对 `/data` 做自动备份、异地复制、恢复演练和保留策略;
|
||||
8. 完成失效证书、泄露响应、重放、中心重启、节点断线和并发规模测试。
|
||||
|
||||
`allowInsecureHttp` 只用于显式允许的私有 IP 内网验证;公网 HTTP 永远拒绝。它不是生产加密替代方案。
|
||||
|
||||
@@ -651,6 +660,7 @@ WxAgent.Host.exe smoke
|
||||
|
||||
```bash
|
||||
curl --fail http://10.1.1.104:18090/healthz
|
||||
curl --fail http://10.1.1.104:18090/readyz
|
||||
|
||||
curl --fail -c /tmp/wxagent.cookies \
|
||||
-H 'Content-Type: application/json' \
|
||||
@@ -714,6 +724,27 @@ curl --fail -H "$AUTH" -H 'Content-Type: application/json' \
|
||||
|
||||
发送任务必须结合任务终态和微信本地历史读回确认;`Succeeded` 代表 Agent 已确认完成调用,不代替业务侧读回核验。
|
||||
|
||||
### 10.4 并发基线
|
||||
|
||||
在 staging 控制面和已注册测试节点上执行;默认只创建 `read-sessions` 读取任务,不执行写任务:
|
||||
|
||||
```bash
|
||||
WXAGENT_SCALE_WEB_PASSWORD='<test-password>' \
|
||||
scripts/control-plane-scale-smoke.py \
|
||||
--base-url http://127.0.0.1:8090 \
|
||||
--node-id node-a --account-id account-a \
|
||||
--requests 100 --workers 10
|
||||
```
|
||||
|
||||
只测就绪接口时不需要 Web 密码或节点参数:
|
||||
|
||||
```bash
|
||||
scripts/control-plane-scale-smoke.py --mode ready \
|
||||
--base-url https://control.example.com --requests 500 --workers 50
|
||||
```
|
||||
|
||||
脚本输出成功数、HTTP 状态分布、p50/p95;每次压测应保存版本、配置、机器规格、数据文件大小和结果,不把结果直接当作 1000 路生产验收。
|
||||
|
||||
## 11. 故障排查
|
||||
|
||||
| 现象 | 优先检查 |
|
||||
@@ -741,7 +772,7 @@ curl --fail -H "$AUTH" -H 'Content-Type: application/json' \
|
||||
|
||||
- 控制面 Docker 镜像构建成功,`/healthz` 返回 `ok/v1`;
|
||||
- Go `go test ./...`、`go vet ./...` 通过;
|
||||
- Core 测试 `166/166` 通过;Service 测试 `20/20` 通过;完整 solution Release build 通过;
|
||||
- Core 测试 `168/168` 通过;Service 测试 `20/20` 通过;完整 solution Release build 通过;
|
||||
- `scripts/remote-control-smoke.sh` 通过,覆盖注册、心跳、任务租约、幂等、结果回传、读取结果保留和拒绝路径;
|
||||
- Windows 节点 `windows-direct-20260911` 在已登录、未锁定会话中上线,注册 `read-sessions`、`read-contacts`、`read-messages` 能力;
|
||||
- 真机 `send-text` 任务 `Pending → Running → Succeeded`,并用文件传输助手本地历史读回唯一标记;
|
||||
@@ -749,9 +780,9 @@ curl --fail -H "$AUTH" -H 'Content-Type: application/json' \
|
||||
|
||||
提交或部署新版本前必须重新执行相关测试。以下条件满足前不能标记生产完成:
|
||||
|
||||
- 控制面 HTTPS、节点 HTTPS/mTLS 和密钥外置;
|
||||
- Token/证书轮换、撤销和泄露响应演练;
|
||||
- 单进程 JSON 存储的备份恢复、并发写入和容量上限验证;
|
||||
- 在实际部署环境启用控制面 HTTPS、节点 HTTPS/mTLS 和 Secret 文件挂载;
|
||||
- 客户端证书撤销、泄露响应和重新签发演练(不包含 Token 轮换);
|
||||
- 自动备份/保留、异地复制、恢复演练、active/passive 故障切换、并发写入和容量上限验证;
|
||||
- 节点/控制面重启、断网、租约过期和 `ResultUnconfirmed` 人工核对;
|
||||
- 真实目标规模、长时间运行、数据保留和日志泄漏扫描;
|
||||
- 当前微信版本变化后的 `doctor`、脱敏 UI 树和 smoke 回归。
|
||||
@@ -759,7 +790,8 @@ curl --fail -H "$AUTH" -H 'Content-Type: application/json' \
|
||||
## 13. 相关文件
|
||||
|
||||
- `control-plane/Dockerfile`:控制面多阶段镜像构建;
|
||||
- `control-plane/server.go`、`protocol.go`、`store.go`:HTTP 路由、协议和持久化;
|
||||
- `control-plane/server.go`、`protocol.go`、`store.go`、`tls.go`:HTTP/TLS 路由、协议、持久化和证书撤销;
|
||||
- `control-plane/compose.production.yml`:Docker Secret、TLS/mTLS 和保留配置的生产示例;
|
||||
- `control-plane/web/`:React 管理端;
|
||||
- `.gitea/workflows/build-web-image.yml`:Gitea 镜像发布;
|
||||
- `node-agent/WxAgent.Service/RemoteAgentHostedService.cs`:节点注册、轮询、任务执行和补传;
|
||||
@@ -767,4 +799,7 @@ curl --fail -H "$AUTH" -H 'Content-Type: application/json' \
|
||||
- `node-agent/WxAgent.Core/RemoteTaskLedger.cs`:本地任务结果账本;
|
||||
- `node-agent/WxAgent.Host/RemoteCliCommands.cs`:远程认证、状态和白名单 CLI;
|
||||
- `docs/validation/Agent-Install-2026-09-11.md`:Windows 安装与真实验证记录;
|
||||
- `scripts/remote-control-smoke.sh`:Linux/临时控制面闭环检查。
|
||||
- `scripts/remote-control-smoke.sh`:Linux/临时控制面闭环检查;
|
||||
- `scripts/control-plane-scale-smoke.py`:就绪/只读任务并发基线;
|
||||
- `scripts/control-plane-data.sh`:控制面数据备份和锁保护的原子恢复;
|
||||
- `scripts/revoke-client-certificate.sh`:计算客户端证书指纹并原子追加撤销列表。
|
||||
|
||||
Reference in New Issue
Block a user