Files
blackbird/docs/reports/auth_service_plan.md
T
qingandWorkBuddy dbc79c52f3 docs(security): 合并 gateway 审计文档并新建 ca 审计索引
- 三份 gateway 审计(20260801/0807/0809)合并为单一 docs/security/gateway_SECURITY_AUDIT.md
- 已完成修复已合入 gateway/src/main.cpp 注释,认证相关项标注迁 ca
- 新建 docs/security/ca_SECURITY_AUDIT.md,同步迁入 P2-3/P1-7/A2 等开放项
- 更新 docs/INDEX.md 审计表、ca/README.md 引用、auth_service_plan/libhttp 文档链接

Co-Authored-By: WorkBuddy <workbuddy@tencent.com>
2026-08-10 00:56:21 +08:00

356 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 认证独立化(CA 模块)开发文档
**日期**: 2026-08-09(v2 重写)
**背景**: gateway v0.8.0 单文件 [main.cpp](../../gateway/src/main.cpp)(2470 行),认证逻辑(约 65%)与反向代理耦合;core/dnfs2 通过 HTTP 回调 gateway 验签,gateway 既是流量入口又是认证权威,形成环形依赖
**范围**: `ca`(新模块)、`gateway`(瘦身为纯代理);**WAF / core / dnfs2 / static / 前端零改动**
**前版**: 2026-08-08 初版计划书(auth 双栈方案)。本版按已选定拓扑重写:**数据流 `waf → ca → gateway`,gateway 不再验签**。原双栈/后置方案见 §2.2 决策记录
---
## 0. 摘要
新建 CA(Central Auth)模块:C++20 服务,接管 gateway 当前监听的 `127.0.0.1:8443`(WAF upstream 不变),承载**全部认证面**(登录/注册/Token 生命周期/CAPTCHA 代理/限流/WS 代理),并作为**认证前置层**:对业务请求本地验签后注入可信身份头,转发给退居 `127.0.0.1:8445` 的 gateway。gateway 删除全部认证代码,不再验签,仅保留白名单反代。
核心收益:验签在 CA 本地完成(RSA 密钥同进程,**零新增网络跳**);core/dnfs2 仍调 `8443` 的 `/admin/verify`、`/whoami`,**无感知切换**;前端 URL 不变;现有黑盒 34 断言原样充当验收门。
---
## 1. 现状分析
### 1.1 当前调用链
```
客户端 ──HTTPS──▶ WAF:443 ──HTTP──▶ gateway:8443 ──HTTP──▶ static:9200 / dnfs2:8006 / core:5200
│ ├─ 本地验签(RSA 内存密钥)+ Cookie 回退 + Authorization 注入
│ ├─ /login /register /logout /refresh_token /whoami /admin/verify
│ ├─ /register/send_code /reset/send_code /reset_password
│ ├─ GET /captcha/image(pymsg 代理 captcha2:8009)
│ └─ WS 代理 /ws/aibox(握手验签 is_admin)
└── pymsg: db:8005 / captcha2:8009 / smtp3:8008 / confs:8010
下游验签回调(HTTP 回环):
core:5200 ──HTTP──▶ gateway:8443/admin/verify (HttpTask.cpp,GATEWAY_HOST/GATEWAY_PORT 可配,fail-closed)
dnfs2:8006 ──HTTP──▶ gateway:8443/whoami (gateway_url 配置项,fail-closed)
```
### 1.2 gateway 职责盘点与归属
| 职责域 | 函数/组件 | 归属 |
|--------|-----------|------|
| 用户认证 | `handleLogin` / `handleRegister` / `handleLogout` / `handleResetPassword` / `handleSendEmailCode` / `handleResetSendCode` | → CA |
| Token 管理 | `verify_token` / `generate_jti` / `revoke_jti` / `revoke_all_user_tokens` / `handleRefreshToken` / `handleWhoami` / `handleAdminVerify` / jti 黑名单 / 用户版本号表 / RSA 密钥对 | → CA |
| 密码体系 | `PBKDF2Hasher` / `PasswordValidator` / 防枚举 dummy 校验 | → CA |
| 验证码/邮箱 | `handleCaptchaImage` / `verify_captcha_remote` / `verify_email_code_remote` | → CA |
| 速率限制 | 全部 RateLimiter 实例(登录 5/5min、注册 3/10min、发码 5/10min + 邮箱级 3/h+10/d、验证码 10/min 等) | → CA |
| WS 代理 | `verifyWsAdminToken` + `_WS_PROXY_ROUTES` 注册循环 | → CA(验签+桥接一体) |
| Cookie | `q4_token` 签发/清除、`extract_token_from_request`(Cookie 回退)、代理时 `Authorization: Bearer` 注入 | → CA |
| HTTP 反代 | `handleProxy`(白名单/路径安全/头转发/XFF) | 留 gateway(去验签化) |
| 头卫生 | `is_special_header` / `is_safe_target` | 留 gateway |
| 基础设施 | `wrapperHttp` / `ConfIni` / `DbC` / `LogC` / 信号处理 / 优雅关闭 | 两侧各持一份(模板见 smtp3) |
### 1.3 核心问题
1. **职责耦合**:认证与代理同进程,任一域改动爆炸半径为全文件
2. **环形依赖**:gateway 是流量入口又是验签权威,core/dnfs2 须 HTTP 回调入口
3. **敏感面混杂**:RSA 私钥、密码哈希校验、jti 黑名单与转发逻辑共用内存空间
4. **不可独立扩展**:认证密集与代理密集负载无法分别扩容;认证状态纯内存,绑定单实例
---
## 2. 目标架构
### 2.1 拓扑
```
客户端 ──HTTPS──▶ WAF:443 ──HTTP──▶ CA:8443 ──HTTP──▶ gateway:8445 ──▶ static:9200 / dnfs2:8006 / core:5200
│
├─ 本地处理:/login /register /logout /refresh_token /whoami /admin/verify
│ /register/send_code /reset/send_code /reset_password
│ GET /captcha/image
├─ WS:/ws/aibox 握手验签(is_admin) → 直接桥接 ws://127.0.0.1:8765
├─ 其余路径:本地验签 → 注入 X-Auth-User/Authorization → 转发 gateway:8445
└─ pymsg: db:8005 / captcha2:8009 / smtp3:8008 / confs:8010
端口安排:CA 接管 8443(WAF upstream 配置不变);gateway 迁 8445(仅 loopback,仅 CA 可达)。
```
职责划分:**CA = 认证权威 + 认证前置代理**;**gateway = 纯路由/转发策略**(opened 白名单、路径安全、XFF 透传)。
### 2.2 决策记录
| 方案 | 拓扑 | 结论 |
|------|------|------|
| **选定:CA 前置** | `waf → ca → gateway` | ✅ 验签在 CA 本地(零网络跳);core/dnfs2 调 8443 不变;WAF/前端不变;gateway 无需新增路径路由机制 |
| 否决 A:CA 后置双栈 | `waf → gateway → ca`(HTTP+pymsg 双栈) | gateway 需新增路径级路由表;CORS/Set-Cookie/错误映射下沉 CA;两服务改动面都大 |
| 否决 B:CA 后置纯 pymsg | `waf → gateway →(pymsg) ca` | gateway 保留 HTTP↔pymsg 翻译层与 Cookie 职责,认证面仍在入口进程内,瘦身不彻底;且每请求多一跳 pymsg 验签或引入吊销延迟的缓存 |
| 否决 C:验签缓存 | gateway 缓存验签结果 60s | logout/改密后 Token 在窗口内仍可用,吊销语义弱化(随拓扑选定自然消失) |
### 2.3 信任模型(重要)
1. **loopback 信任基线不变**:本架构 loopback 内部服务本就不互鉴权(db:8005 execute 无认证即先例)。gateway:8445 仅绑 `127.0.0.1`,与本基线一致。
2. **身份头契约(strip-then-set)**:CA 在边缘剥离客户端伪造的 `X-Auth-User` / `X-Auth-Admin`(Beast fields 大小写不敏感,`erase` 后 `set`),验签通过才注入。模式 A 下 CA 的唯一上游是 WAF(loopback)。
3. **gateway 存在性不变量**:显式 `Target-Url` 请求必须携带 `X-Auth-User`,否则 401(非验签,仅防线编程,防本地误直连/SSR​​F 兜底)。
4. **模式 B 警示迁移**:CA 直连公网(无 WAF)时 XFF 可被伪造、限流可绕过——原 gateway README 的 A4 降级提示随限流一并迁入 CA README;根治方案 [libhttp_remote_addr_dev_doc.md](libhttp_remote_addr_dev_doc.md) 中的 `trust_xff`/`rate_limit_key()` 配套改在 CA 落地。
---
## 3. CA 模块设计
### 3.1 目录与构建(沿用 smtp3/captcha2 约定)
```
ca/
├── src/main.cpp # 入口 + HTTP 路由 + 认证逻辑 + 前置转发(迁移代码为主)
├── inc/
│ ├── Conf.hpp # ConfIni(confs 拉取 + env 覆盖 + 完整性校验)
│ ├── DbC.hpp # 自 gateway 随迁(已基于 libmsg us/Msg.hpp;client 名 "gateway"→"ca")
│ ├── LogC.hpp # 异步日志(smtp3 长连接版)
│ ├── ExpBase.hpp # 异常基类
│ └── LocalTime.hpp # 时间工具
├── Makefile # 链接 us_http / us_msg / us_crypt / ssl / crypto / boost_json / curl
├── _set.sh / _run.sh
└── README.md
```
- 二进制 `ca.bin`;版本从 `1.0.0` 起;日志服务名 `ca`
- 依赖:libhttp(HttpServer/HttpClient/ws_proxy)、libmsg(MsgClient/RpcClient)、libcrypt(MyRSA/Base64)、OpenSSL(PBKDF2/RAND_bytes)、boost::json/program_options/property_tree、libcurl
- **不依赖 libsqlite3**:Users 表访问全部经 db:8005(现状即如此)
### 3.2 配置(`confs/configs/ca.ini` 新增)
```ini
[Server]
address = 127.0.0.1
port = 8443 # 接管 gateway 现端口,WAF upstream 不变
[Upstream]
gateway = http://127.0.0.1:8445 # 业务请求唯一上游
[Token] # 自 gateway.ini 原样迁入
keep_time = 3600
refresh_grace_multiplier = 2
max_refresh = 10
[Admin] # 原样迁入
users = 1776177662@qq.com;277665039@qq.com;
[WsProxy] # 自 gateway.ini 迁入
routes = /ws/aibox=ws://127.0.0.1:8765;
[CORS] # 原样迁入(P2-3:预检反射由 libhttp 处理,白名单暂仍不生效)
allowed_origins = https://qsont.me;https://www.qsont.me;http://127.0.0.1:8443;http://localhost:8443
[Downstream] # 原样迁入
db_host = 127.0.0.1
db_port = 8005
captcha_host = 127.0.0.1
captcha_port = 8009
smtp_host = 127.0.0.1
smtp_port = 8008
```
环境变量覆盖(与 gateway 现机制一致):`LISTEN_ADDR`/`LISTEN_PORT`、`UPSTREAM_GATEWAY`、`DB_*`、`CAPTCHA_*`、`SMTP_*`、`CONFS_HOST`/`CONFS_PORT`。配置加载:confs `get` 拉取(retry_on_refused 阻塞)→ env 覆盖 → 完整性校验。
### 3.3 HTTP 路由表(对外契约与原 gateway 完全一致)
| 路由 | 处理 | 说明 |
|------|------|------|
| POST `/login` | 本地 | 强制远端 CAPTCHA;dummy PBKDF2 防枚举;签发 Token + `q4_token` Cookie |
| POST `/register` | 本地 | 密码强度→邮箱格式→CAPTCHA→邮箱验证码(smtp fail-closed)→写 Users |
| POST `/register/send_code`、`/reset/send_code` | 本地 | IP+邮箱级限流、强制 CAPTCHA、smtp 60s 冷却 429 透传 |
| POST `/reset_password` | 本地 | 防枚举恒成功文案;改密后版本号递增全设备吊销 |
| POST `/logout` | 本地 | jti 吊销 + 清 Cookie |
| POST `/refresh_token` | 本地 | 宽限期刷新、旧 jti 吊销、max_refresh 上限 |
| POST `/whoami` | 本地 | 恒 200,`{login:false}` 不泄露细节;core/dnfs2 依赖此契约 |
| POST `/admin/verify` | 本地 | fail-closed 401;core 依赖此契约 |
| GET `/captcha/image` | 本地 | pymsg 调 captcha2,PNG + `X-Captcha-Token` + `no-store`,10/min/IP |
| WS `[WsProxy]` 路径 | 本地 | 握手验签 `is_admin=true` → 桥接后端(ws/wss),双向透传 |
| GET/POST `*`(通配) | **转发** | 见 §3.4 |
### 3.4 前置转发层(通配路由 → gateway:8445)
迁移 `handleProxy` 的转发骨架,认证语义前置:
1. **路径安全**:`is_safe_target()` 校验(`..`/`%2e`/`%2f`/`%5c`/空字节 → 400),CA/gateway 双层各执行一次(防线叠加,gateway 侧保留原校验)。
2. **公开 vs 受保护**:无 `Target-Url` 头 → 公开目标(Proxy.default 语义在 gateway),**剥离**客户端 `X-Auth-User`/`X-Auth-Admin` 后直接转发,不注入任何凭证。
3. **受保护**:有 `Target-Url` → 提取 Token(`Authorization` 优先,回退 `q4_token` Cookie)→ `verify_token` 本地验签(RSA→过期→jti→版本号)→ 失败按现契约 400/401,**不转发**;成功则注入:
- `Authorization: Bearer <token>`(Cookie 来源也统一补齐,dnfs2 等下游零改动)
- `X-Auth-User: <email>`、`X-Auth-Admin: true`(仅管理员;供 gateway 不变量与下游未来免回调使用)
4. **头卫生**:剥离客户端自带的 `X-Auth-User`/`X-Auth-Admin`(strip-then-set);XFF 透传 WAF 值(缺省 `unknown`);`Host`/`connection`/`Accept-Encoding` 等逐跳头处理沿用现 `is_special_header` 集合 + `x-auth-user`/`x-auth-admin` 新增。
5. **转发失败语义**:gateway:8445 不可达 → 502(与现 captcha/smtp fail-closed 风格一致),记 warning 日志。
6. **响应**:状态码与响应头原样回传(现 `handleProxy` 行为),`Connection: close`。
### 3.5 迁移资产清单(gateway `main.cpp` → CA `main.cpp`)
代码以**整体搬迁**为主,保持实现逐字不变(降低回归面),仅做两处适配:日志服务名 `gateway`→`ca`;DbC client 名同上。
| 资产 | 备注 |
|------|------|
| PBKDF2Hasher / PasswordValidator / 常数时间比较 | 含 SHA256 旧哈希迁移注释块(保持注释状态) |
| TokenInfo / verify_token / generate_jti / revoke_jti / revoke_all_user_tokens / jti 黑名单(5000 上限清理)/ 用户版本号表 | RSA 密钥对启动内存生成(重启即全吊销,语义不变) |
| 8 个 RateLimiter 实例 + 邮箱级双窗口限流 | 限流键仍取 XFF(模式 A 可信;模式 B 警示见 §2.3-4) |
| handleLogin ~ handleResetPassword 全部 handler | 错误文案/状态码契约逐字保留(黑盒断言依赖) |
| handleWhoami / handleAdminVerify / handleRefreshToken / handleLogout | 同上 |
| handleCaptchaImage / verify_captcha_remote / verify_email_code_remote | fail-closed 语义保留 |
| verifyWsAdminToken + ws_proxy 注册 | 桥接目标直接为后端(不再经 gateway) |
| handleProxy 转发骨架 / is_safe_target / is_special_header / get_cookie_value / extract_token_from_request | 按 §3.4 改造 |
| wrapperHttp / 信号处理 / 优雅关闭(8s+3s 超时)/ ExpBase / ConfIni / LocalTime / DbC / LogC | 基础设施随迁 |
### 3.6 不变量自检(启动时)
- `[Upstream] gateway` 非空且为 `http://127.0.0.1:*`(防误配到公网)
- 模式 B 检测:`Server.address` 非 loopback 时启动日志打印 A4 安全降级警告
---
## 4. gateway 瘦身设计(v0.9.0)
### 4.1 删除清单(预计 -1700 行,2470 → ~750 行)
- 全部认证 handler 与 Token/PBKDF2/RSA/jti/版本号/限流/CAPTCHA/邮箱验证码代码
- `q4_token` Cookie 读写、`extract_token_from_request`、代理内验签与 Authorization 注入
- `[Token]`/`[Admin]`/`[WsProxy]`/`[Database]` 配置读取;下游 captcha/smtp 配置(db 保留供 LogC)
- `/login` 等 9 条认证路由 + `/captcha/image` 路由 + WS 代理注册循环
### 4.2 保留清单
- `handleProxy`(去验签化)+ `is_safe_target` + `is_special_header` + `wrapperHttp`
- 存在性不变量:显式 `Target-Url` 且无 `X-Auth-User` → 401(§2.3-3)
- 公开目标规则:无 `Target-Url` → `Proxy.default`,不校验身份头
- XFF 处理:透传 CA 值(缺省 `unknown`)
- 配置加载、信号处理、优雅关闭、LogC
### 4.3 精简后 `confs/configs/gateway.ini`
```ini
[Server]
address = 127.0.0.1
port = 8445 # 迁出 8443;仅 CA 可达
tls = off
[Proxy]
default = http://127.0.0.1:9200
closed = http://127.0.0.1:8005;http://127.0.0.1:8007;
opened = http://127.0.0.1:9200;http://127.0.0.1:8006;http://127.0.0.1:5200;
[Downstream] # 仅供 LogC 日志落库
db_host = 127.0.0.1
db_port = 8005
```
### 4.4 启动自检
- `Server.address` 必须为 loopback(`127.0.0.1`/`::1`):gateway 不再验签后,绑定公网等于裸奔,**非 loopback 直接拒绝启动**并打印致命错误。
---
## 5. 接口契约
### 5.1 对外 HTTP(不变量)
`https://<host>/login`、`/register`、`/whoami` 等全部 URL、请求/响应 JSON 结构、状态码(400/401/403/429/500/502)、`q4_token` Cookie 属性、`X-Captcha-Token` 头——**逐字不变**。前端、WAF、core、dnfs2 零改动的依据即此。
### 5.2 内部头契约(CA ↔ gateway ↔ 下游)
| 头 | 方向 | 语义 |
|----|------|------|
| `X-Auth-User` | CA→gateway→下游 | 已验签身份;CA strip-then-set;gateway 对显式 Target-Url 要求其存在 |
| `X-Auth-Admin` | CA→gateway→下游 | `true` 表示管理员;供下游免回调豁免(可选消费) |
| `Authorization` | CA→gateway→下游 | Cookie 来源统一补齐为 Bearer;下游解析不变 |
| `X-Forwarded-For` | WAF→CA→gateway→下游 | 逐层透传,缺省 `unknown` |
| `Target-Url` | 客户端→CA→gateway | 路由策略头,语义不变 |
### 5.3 Token 格式(不变)
`Base64(payload)_RSA-Sign(payload)`;payload 字段(user/jti/ver/iat/created_at/keep_time/is_admin/refresh_count/max_refresh)不变。切换瞬间旧 Token 全部失效(CA 新密钥),用户重新登录——一次性事件,cutover 通告中说明。
### 5.4 下游零改动验证点
| 消费方 | 现状调用 | 切换后 |
|--------|----------|--------|
| core `verify_admin_token` | `http://127.0.0.1:8443/admin/verify` | 同 URL 由 CA 服务,契约不变 |
| dnfs2 Token 验签 | `http://127.0.0.1:8443/whoami` | 同上 |
| static `/api/check_user` | 直连 db 查 Users(账号旁路) | 不受影响;遗留项另行收口 |
---
## 6. 上线步骤(cutover 与回滚)
| 步骤 | 内容 |
|------|------|
| 1 | CA 开发完成,`LISTEN_PORT=18443` 并行实例联调(不影响现网 8443) |
| 2 | gateway 瘦身版(v0.9.0)构建,`gateway.ini` 改 8445 |
| 3 | cutover(秒级窗口):停 gateway:8443 → 启 CA:8443 → 启 gateway:8445 → 黑盒全量验证 |
| 4 | `core/init.txt` 增加 `ca/_run.sh`(gateway 之前);README/INDEX 文档同步 |
| 5 | 观察 24h:CA/gateway 日志、db Logs 表 4xx/5xx 基线对比 |
**回滚**:停 CA → 旧 gateway 二进制 + 旧配置回 8443 → 重启。Token 全部重签(用户重新登录),无数据迁移。
---
## 7. 测试计划
### 7.1 验收门(零改动复用)
- `tests/blackbox/test_gateway.py` 34 断言**原样**对 8443 执行:认证路径打到 CA、代理路径经 CA→gateway,外部契约不变则全绿(当前基线 32 passed / 2 env-skipped)
- 修复期两个红测试(A3 缺字段 400)已在 v0.8.0 转绿,迁移后必须保持
### 7.2 新增探针(test_ca.py,黑盒补充)
| 探针 | 预期 |
|------|------|
| 客户端伪造 `X-Auth-User: admin@x` + 显式 Target-Url(无 Token) | CA 剥离后 401,不到下游 |
| 伪造 `X-Auth-User` + 有效非管理员 Token 访问 WS 路由 | 403(以验签结果为准,不以头为准) |
| 直连 gateway:8445,显式 Target-Url、无 `X-Auth-User` | 401(存在性不变量) |
| 经 CA 全链路(8443)带 Token 访问 dnfs2 | 下游收到 `X-Auth-User` 与 `Authorization` |
| CA 存活、gateway:8445 停止 | 业务路径 502(不静默放行),认证路径正常 |
| gateway 存活、CA 停止 | WAF 502(入口不可达,符合预期 fail-closed) |
| 公开目标(无 Target-Url)带伪造身份头 | 下游收不到 `X-Auth-User`/`Authorization` |
### 7.3 集成回归
- core HTTP 管理接口(`/admin/verify` 链路)实测;dnfs2 笔记 CRUD(`/whoami` 链路 + AI 审核)实测
- WS 代理端到端:管理员 Token 升级 `/ws/aibox` 双向帧;非管理员 403
- 限流全谱在 CA 复测(随机 XFF 技巧沿用);cutover/回滚演练各一次
### 7.4 测试资产演进(后续)
- `test_gateway.py` 按进程边界拆分为 `test_ca.py`(A/B/C/E 段)+ 精简 `test_gateway.py`(D 段代理矩阵 + 8445 直连探针),README/INDEX 同步
- 认证 happy path 仍依赖 captcha2/smtp 测试钩子(既有遗留,CA 落地后可仅在 CA 层加 `[Security] captcha_required` 开关,单点解锁)
---
## 8. 风险与缓解
| 风险 | 等级 | 缓解 |
|------|------|------|
| CA 不可用 → 全站入口中断 | 高 | CA 职责内聚后可用性等同于现 gateway;core 守护 + 黑盒监控;回滚方案秒级 |
| 迁移遗漏导致认证行为漂移 | 中 | 代码逐字搬迁 + 34 断言验收门 + §7.2 探针矩阵 |
| 身份头伪造/泄露 | 中 | strip-then-set + gateway 存在性不变量 + 公开目标不注入 + 直连探针回归 |
| gateway:8445 被公网暴露 | 高 | 启动强制 loopback 自检(§4.4);部署审计 checklist 增加端口扫描项 |
| cutover 窗口 Token 全失效 | 低 | 预期内(RSA 换钥),通告用户重新登录 |
| 双重转发延迟 | 低 | 本机 HTTP 转发 <1ms;CA→gateway 短连接可后续优化为 keep-alive |
| 模式 B 限流绕过(A4 迁移) | 中 | CA README 降级警示;根治按 libhttp_remote_addr_dev_doc(配套改落 CA) |
---
## 9. 工作量估算
| 部分 | 规模 | 估时 |
|------|------|------|
| CA 脚手架(目录/Makefile/_set.sh/_run.sh/LogC 等) | 模板复制 + 适配 | 0.5 天 |
| 认证资产搬迁 + 前置转发层改造 | ~1700 行搬迁 + ~150 行改造 | 1.5 天 |
| gateway 瘦身 + 启动自检 | -1700 行 + ~20 行 | 0.5 天 |
| 配置/init.txt/文档(README×2、INDEX、confs) | — | 0.5 天 |
| 黑盒验收 + §7.2 探针 + 集成回归 + cutover 演练 | — | 1 天 |
| **合计** | | **4 天**(含缓冲) |
---
## 10. 与既有文档的关系
- 本文档**替代** 2026-08-08 初版计划书中的双栈拓扑与阶段划分(初版的职责盘点/迁移清单仍然有效,已并入 §1.2/§3.5)
- [libhttp_remote_addr_dev_doc.md](libhttp_remote_addr_dev_doc.md)(A4 根治):实施时 `trust_xff`/`rate_limit_key()` 配套由 gateway 改为落 CA;`is_special_header` 两侧同步加 `x-remote-addr`
- [gateway_SECURITY_AUDIT.md](../security/gateway_SECURITY_AUDIT.md):A2(白名单 403)断言、P2-3(CORS 白名单)随转发层/配置迁入 CA;P1-7(CSRF Token)在 CA 层评估
- gateway README / 项目 README 的架构图、端口表、请求链路在上线步骤第 4 步同步更新