Files
blackbird/docs/SECURITY_HARDENING_PLAN.md
T

6.7 KiB
Raw Blame History

micro_servers 内网通信安全加固 · 开发计划

项目:qing/micro_servers(DIY 轻量微服务框架) 场景:单机部署(所有服务同一台,仅 waf:443 对外) 目标:在"单机 + 绑 127.0.0.1"基础上,补齐服务间认证与加密 状态:计划 v1.0


0. 决策摘要(来自需求讨论)

问题 结论
内网是否需要独立鉴权 网络隔离为主(绑127.0.0.1),高危面另加服务间认证
能否用用户密钥做认证 对外链路可用;服务间互调改用独立 service key
能否用 RSA+AES 通信加密 能,但单机场景 RS‌A 公钥分发太麻烦,不划算
最终方案 core 生成进程组密钥 → 环境变量注入 → AES-GCM 服务间加密
分发方式 由 core 作为密钥生成/分发中心,免手动拷贝

1. 总体目标

为 micro_servers 的内网服务间通信建立三层防线:

  1. 隔离层(地基):所有内部服务绑定 127.0.0.1,云安全组仅放行 443
  2. 认证层:服务间调用携带共享密钥(进程组密钥)校验身份
  3. 加密层:敏感通信用 AES-256-GCM 加解密 + 完整性 + 防重放

2. 架构变更(目标态)

                   外网攻击者 ──只能到达──► 只开放 waf:443
                                              │
                     ┌────────────────────────┴───────────┐
                     │        core (:5200, 本机)           │
                     │   [密钥生成器] 生成进程组密钥         │
                     │   通过环境变量 MICROSERV_KEY 注入     │
                     └─────┬──────────────────────────────┘
                           │ 拉起 + 注入密钥
     ┌────────┬────────┬───┴───┬────────┬────────┬─────────┐
     ▼        ▼        ▼        ▼        ▼        ▼
   waf      gateway  static   dnfs     db      ai_review ...
   :443     :8443    :9200    :8006    :8005     :8007
   全部绑定 127.0.0.1(仅本机可达)
   服务间调用:AES-GCM 加密 + 进程组密钥认证

3. 工作分解(3 阶段)

阶段一:隔离加固(P0,先行)

对齐"绑 127.0.0.1 + 只放行 443"的基线。

  • 1.1 检查并修改所有服务监听地址为 127.0.0.1(禁止 0.0.0.0)
    • waf 例外:443 对外;但可考虑 waf 内部转发目标为 127.0.0.1:8443
  • 1.2 云安全组 / ufw:仅放行 TCP 443,其余端口公网关闭
    • 规则示例:ufw default deny incoming + ufw allow 443/tcp
  • 1.3 验证:从外网 curl 各内部端口(8443/9200/8005…)应全部超时/拒绝
  • 1.4 验证:本机 curl http://127.0.0.1:8443 正常(确认仅本机可达)

完成标准:对外仅 443 一个口,内部端口公网不可达。


阶段二:core 密钥生成 + 环境变量注入(P1 核心)

实现"core 作为进程组密钥中心"。

  • 2.1 core 启动时生成随机密钥
    • 实现:openssl rand -hex 32(或 C++ 读取 /dev/urandom 256 位)
    • 输出:32 字节(256 位)十六进制串作为进程组密钥
  • 2.2 core 拉起子进程时注入环境变量
    • 用 execve 的 envp 直接传 MICROSERV_KEY=<key>(勿用全局 export,减少暴露)
    • 涉及子进程:ai_review/db/dnfs/smtp/static/waf/gateway/captcha/aibox
  • 2.3 子进程侧读取密钥
    • 各服务启动时读 os.environ["MICROSERV_KEY"]
    • fail-fast:读不到立即报错退出,禁止静默降级为明文
  • 2.4 core 接口安全复核
    • core(:5200) 必须:只绑 127.0.0.1 + 管理接口带鉴权
    • 说明:core 现为"主钥匙",是最高价值目标,重点保护

完成标准:所有由 core 拉起的服务均带 MICROSERV_KEY,缺失时报错退出。


阶段三:服务间 AES-GCM 加密通信(P1)

用预共享的进程组密钥加密服务间流量。

  • 3.1 编写统一加解密库 microcrypt
    • 目标语言:Python(pymsg/Flask 服务)+ C++(gateway)各一份,接口对齐
    • 算法:AES-256-GCM
      • 加密:随机 12 字节 nonce + 明文 → (nonce, ciphertext, tag)
      • 解密:nonce + tag 校验,失败即拒绝
    • 防重放:帧内携带时间戳/序号,接收方校验新鲜度
  • 3.2 接入 pymsg 帧(db/captcha/smtp/confs 等基于 pymsg 的服务)
    • 在长度前缀帧的 payload 外包一层 GCM 加密
  • 3.3 接入 HTTP 服务(static/dnfs/ai_review/gateway 的互相调用)
    • 敏感请求体加密,或至少加认证 header + 加密关键字段
  • 3.4 密钥轮换
    • core 重启即换新密钥(进程生命周期天然轮换)
    • 配置项:可设定期轮换(可选,P2)
  • 3.5 回归测试
    • 正常链路:注册/登录/笔记 CRUD/日志上报 全流程可跑通
    • 故障测试:错误密钥/乱序/篡改 → 服务应拒绝而非崩溃

完成标准:服务间敏感通信已 GCM 加密,篡改/伪造被拒。


4. 风险与对策

风险 对策
环境变量对同机进程可见(/proc//environ) 接受局限:威胁模型以"防外网"为主;不把 key 当终极秘密;仅绑本机+少暴露
core 被攻破 → 主钥匙泄露 将 core 作为最高价值目标:绑本机、接口精简、强鉴权、最小权限
调试时手动跑单服务导致 key 缺失/不一致 fail-fast 报错 + 统一由 core 拉起,文档明确"禁止手动裸跑"
AES-GCM 误用(nonce 重用等) 库内统一封装,nonce 每次随机生成;禁止外部传入
明文降级残留 fail-fast + 代码审查禁止"No key → 明文"分支

5. 里程碑

里程碑 内容 预估
M1 阶段一:隔离加固完成,对外仅 443 0.5 天
M2 阶段二:core 密钥注入 + 子进程读取 1 天
M3 阶段三:AES-GCM 库 + 接入全部服务 2-3 天
M4 回归测试 + 安全验证(篡改/伪造/重放) 1 天

6. 验证清单(上线前)

  • 外网端口扫描:仅 443 开放
  • 内部端口仅 127.0.0.1 可达
  • 所有 core 拉起服务均带 MICROSERV_KEY
  • 缺失密钥 → 服务 fail-fast 报错(无明文降级)
  • 错误/篡改密文 → 服务拒绝请求
  • 完整业务链路回归通过
  • MICROSERV_KEY 未提交进 git(.env/.gitignore)

7. 备注 / 后续可选项(P2)

  • 密钥定期轮换定时器
  • mTLS 升级路径(若未来改多机部署)
  • 审计日志:记录服务间认证失败/解密失败事件