# 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=`(勿用全局 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 升级路径(若未来改多机部署) - 审计日志:记录服务间认证失败/解密失败事件