- Rename SECURITY_HARDENING_PLAN.md -> SECURITY_HARDENING_PLAN_20260803.md - Rename aibox_SECURITY_AUDIT.md -> aibox_SECURITY_AUDIT_full_20260801.md - Update INDEX.md links accordingly
153 lines
6.7 KiB
Markdown
153 lines
6.7 KiB
Markdown
# micro_servers 内网通信安全加固 · 开发计划
|
||
|
||
> 项目:qing/micro_servers(DIY 轻量微服务框架)
|
||
> 场景:单机部署(所有服务同一台,仅 waf:443 对外)
|
||
> 目标:在"单机 + 绑 127.0.0.1"基础上,补齐服务间认证与加密
|
||
> 状态:计划 v1.0
|
||
|
||
---
|
||
|
||
## 0. 决策摘要(来自需求讨论)
|
||
|
||
| 问题 | 结论 |
|
||
|------|------|
|
||
| 内网是否需要独立鉴权 | 网络隔离为主(绑127.0.0.1),高危面另加服务间认证 |
|
||
| 能否用用户密钥做认证 | 对外链路可用;服务间互调改用独立 service key |
|
||
| 能否用 RSA+AES 通信加密 | 能,但单机场景 RSA 公钥分发太麻烦,不划算 |
|
||
| 最终方案 | **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/<pid>/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 升级路径(若未来改多机部署)
|
||
- 审计日志:记录服务间认证失败/解密失败事件
|