OpenClaw—AI研究OpenClaw—AI研究
  • AI动态
  • OpenClaw教程
  • 技术解读
  • 用户故事

【开发日志】Publishing System 开发全记录六(6月2日)

【开发日志】Publishing System 开发全记录六(6月2日)

2026年6月2日 by WoodStone

【开发日志】Publishing System 开发全记录六(6月2日)

今天是打硬仗的一天!昨天搭的 HermesAgent 接收端,今天要给控制端加”安检”——HMAC 签名、IP 白名单、MySQL 审计三层防护全上。还有那个图片迁移问题,今天终于做到”自包含”:源站关了 ws 也能独立运行。

一、图片迁移”自包含”

之前 sg2 直接下载图、改 URL 拼到 content 里,问题是跨地区访问慢且 ws 服务器无图。新加 POST /api/hermes/v1/media/upload,ws 自己收 URL、自己存、自己回传路径。返回相对路径(不带域名),浏览器自动拼当前域名。文件用 <md5[:8]>_<name> 命名防冲突,目录 /uploads/<yyyy>/<mm>/。再加 nginx location ^~ /uploads/ 直服务,绕过 Next.js 静态 cache。源站 temp 可以随时关,ws 站完全独立。

三层防护示意图

图1是今天搭起来的整个 v6 防护体系。从外到内三层:IP 白名单(第一道,过滤失陷机器)、HMAC 签名(第二道,防密钥泄露伪造)、MySQL 审计(第三道,可追溯任何操作)。任意一层失败都记录到审计表里,后台能实时看。

二、HMAC-SHA256 双向认证

sg2 的 .sh 文件放明文 token 是隐患。改成签名协议:X-Hermes-Key 标识客户端指纹、X-Hermes-Timestamp 时间戳、X-Hermes-Signature 签名。签名串 = METHOD\nPATH+QUERY\nTS\nSHA256(BODY)。客户端只存 fingerprint 和一个独立 ~/.hermes/key 文件(chmod 600),真实密钥只在 ws 服务器 .env.local 里。客户端 .sh 泄露不会泄露服务端密钥。

HMAC 签名流程图

图2是签名流程。客户端用 fingerprint 找本地 key 签请求,服务端用 fingerprint 找服务端 key 验签。中间不传明文 token,流量被监听也造不出合法签名。配合 IP 白名单就算 key 泄露,攻击机器也不在白名单——双重保险。这里有个隐蔽 bug:new URL().pathname 丢 query,签名不匹配。修法是 pathname + search。

三、IP 白名单 + MySQL 审计

HMAC 防”密钥泄露伪造”,但防不了”白名单机器上的恶意程序”。加 IP 白名单:HERMES_ALLOWED_IPS=43.160.224.0/24(sg2),支持 CIDR 解析。客户端 IP 优先级 x-forwarded-for → x-real-ip → request.ip,反代后面也能识别。

审计表 hermes_audit_logs 在 ws 的 publishing_system 库。字段:ts / fingerprint / client_ip / method / path / action / target_id / result / reason。每次请求都写一行:成功 success、拒绝 reject(含原因)。写审计用 .catch(() => {}) 防止审计失败阻塞主请求——审计是辅助,绝不能让主业务因审计失败挂掉。

审计后台面板

图3是后台审计页面实际效果。3 张统计卡片(24h 成功绿/拒绝红/错误黄)+ 4 字段筛选(结果/Fingerprint/IP/按钮)+ 表格列。加分:实时刷新(每 5s 拉一次,新条目显示”+N 新增”徽章+脉冲点)、导出 CSV(按筛选条件,UTF-8 BOM 兼容 Excel)、方法彩色标签(GET 蓝/POST 绿/DELETE 红)。

四、关键 bug 修复

今天踩了 4 个经典坑:

  • 路径只取 pathname:new URL().pathname 丢 query,签名不匹配 → 改用 pathname + search
  • $() 退出码丢失:command substitution 改写真实退出码为 0 → 先跑抓 $? 再读 stdout
  • getPostBySlug 没 join users:详情页 author_name 永远 NULL → 补 LEFT JOIN users u
  • 500 vs 200 状态码:下载失败时返回 5xx 让客户端误判服务器故障 → 改 200 + success:false

第 2 个最坑——$() 替换返回值永远是 0(子 shell 成功),被调命令真实退出码丢了。修法:把命令和赋值拆成两步。这也解释了 ws 服务器之前 9 条审计全 reject 的根因:签名失败但脚本以为成功——整个批量迁移的图全丢了,全靠 fallback 机制从主域拉回来。

五、今天就到这里

从早上”图片自包含”开始,到下午”HMAC 签名 + IP 白名单 + MySQL 审计”三层防护,再到晚上”后台可视化页面”,整个 v6 防护体系搭起来了。纯粹是把”玩具级”内部工具升级到”生产级”,没改任何业务逻辑。下次目标:

  • 审计页加”声音告警”(关键安全事件)
  • WebSocket 推送(替代轮询)
  • 客户端凭据轮换(90 天换 key)
  • 多 fingerprint 支持(已有基础设施)

今天就到这里,休息一下。

关于作者:WoodStone,技术爱好者,专注于 AI 和 Web 开发。

记录时间:2026年6月2日

← 返回文章列表
分类: 技术解读 标记: Claude, OpenClaw

© 2026 OpenClaw—AI研究 版权所有

沪ICP备2026010690号-1