sub2api/proxy-ng/README.md
zizi 6814fa2a62 docs(ops): record proxy-ng deployment hardening
Add deployment traces for the JPpro proxy node, RackNerd origin hosts, catproxy boundary changes, local speed checks, and Sub2API rate-limit behavior.

Keep remote secrets excluded while tracking sanitized nginx, compose, plan, and operational memory documents.
2026-05-26 23:27:41 +08:00

208 lines
9.5 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.

# proxy-ng 多节点中转方案
日期2026-05-25
## 结论
方案可行:一个域名可以解析到多个 proxy-ng 节点,每个节点运行 nginx 反向代理,再把请求转发到同一个 sub2api 后端。sub2api 前面需要有一个后端入口网关,只允许这些 proxy-ng 节点访问,并校验共享密钥,避免后端公网端口被扫到后被直接利用。
最小推荐拓扑:
```mermaid
flowchart LR
U[用户] --> D[同一域名<br/>多 A/AAAA 记录]
D --> N1[proxy-ng 节点 A<br/>nginx]
D --> N2[proxy-ng 节点 B<br/>nginx]
D --> N3[proxy-ng 节点 C<br/>nginx]
N1 --> B[后端入口网关<br/>校验节点 IP + 共享密钥]
N2 --> B
N3 --> B
B --> S[sub2api :8080]
S --> P[(PostgreSQL)]
S --> R[(Redis)]
```
## 关键设计
### 1. 一个域名配置多个 IP
可行,但有边界:
- 普通 DNS 多 A 记录只能做粗粒度轮询,不能保证按节点健康状态实时摘除故障节点。
- 如果需要健康检查、故障摘除、权重、地区路由,必须使用 Cloudflare Load Balancing、DNS 服务商健康检查,或自建调度。
- 只配置多个 A 记录时,某个 proxy-ng 节点宕机后,仍可能有用户解析到坏 IP直到 DNS 缓存过期。
推荐阶段:
| 阶段 | DNS 方案 | 适用场景 |
|---|---|---|
| P0 | 多个 A 记录TTL 60-300 秒 | 节点少、可接受短暂失败 |
| P1 | Cloudflare Load Balancing 或同类健康检查 | 要求自动故障摘除 |
| P2 | 按地区/运营商调度 | 有明确区域访问质量目标 |
### 2. proxy-ng 节点职责
proxy-ng 节点只做入口和转发,不保存业务状态:
- TLS 终止或透传到后端入口网关。
- 限流、连接数控制、请求体大小限制。
- 透传真实客户端 IP 链路。
- 给后端入口网关注入节点共享密钥。
- 健康检查自身 nginx 和后端可达性。
proxy-ng 节点不应该持有 sub2api 管理员账号、数据库密码、Redis 密码、业务 API Key也不提供账号出口代理能力。
### 3. 后端入口网关职责
后端入口网关可以是后端服务器上的 Caddy 或 nginx放在 sub2api 前面:
- 只允许 proxy-ng 节点公网 IP 访问后端入口端口。
- 校验 `X-Proxy-Ng-Token` 共享密钥。
- 校验通过后删除密钥头,再转发给 sub2api。
- 统一写入 `X-Forwarded-For` / `X-Real-IP`
- sub2api `server.trusted_proxies` 只信任后端入口网关或最后一跳代理。
密钥不是替代防火墙的安全边界。正确做法是“来源 IP 白名单 + 密钥校验 + TLS 回源”同时存在。
### 4. sub2api 内置节点管理
如果要求“在 sub2api 应用内管理 proxy-ng 节点和密钥”,也可行,但这是代码改造,不是单纯运维配置:
- 新增 inbound proxy node 配置或数据模型,至少包含节点名、节点公网 IP/CIDR、密钥哈希、启停状态、备注。
- 在 Gin 全局中间件里校验来源 IP 和 `X-Proxy-Ng-Token`,校验失败直接 403。
- 支持双 token 轮换,避免所有节点同时停机换密钥。
- 管理端需要提供节点增删改查和密钥重置入口。
第一版不建议直接改 sub2api 业务代码。先用后端入口网关完成 IP 白名单和密钥校验,复杂度更低,回滚也更干净。
### 5. 账号出口代理池独立
sub2api 的账号代理不属于 proxy-ng 节点职责。账号出口代理池应独立建设和管理:
- proxy-ng 只优化用户到 sub2api 的入口线路。
- sub2api 账号访问上游模型/API 时,继续使用现有代理管理里的 `proxy_id`
- 这些账号代理可以来自独立代理池、第三方代理、专用出口节点或其他合规网络资源。
- proxy-ng 节点不暴露 `1080``7890``mixed``socks` 等出口代理端口。
- 不在 proxy-ng 节点上部署 sing-box、Clash、Xray 等出口代理服务。
这个边界可以避免 proxy-ng 节点变成开放代理风险点,也避免入口中转带宽和账号出口流量互相抢资源。
## 会出问题的步骤
### 高风险
1. **只做多 A 记录但没有健康检查**
节点宕机时 DNS 仍可能返回坏 IP。用户表现为随机失败不是全部失败。
处理方式P0 接受这个限制P1 引入 Cloudflare Load Balancing 或 DNS 健康检查。
2. **后端公网端口只靠隐藏 IP**
后端 IP 可能被扫到。只要后端入口没有 IP 白名单和密钥校验,攻击者可以绕过 proxy-ng 直接打 sub2api。
处理方式:后端防火墙只放行 proxy-ng 节点 IP入口网关校验 `X-Proxy-Ng-Token`sub2api 容器端口不直接暴露公网。
3. **真实客户端 IP 链路配置错误**
当前 sub2api 限流器使用 Gin `c.ClientIP()`,它依赖 `server.trusted_proxies`。配置错会导致所有用户被当成同一个节点 IP登录/注册/API Key ACL 都可能异常。
处理方式:只信任最后一跳后端入口网关,端到端验证登录限流和 API Key IP ACL。
4. **共享密钥轮换没有计划**
如果所有 proxy-ng 节点共用一个密钥,泄露后必须同步更新所有节点和后端入口网关。
处理方式:后端入口支持至少两个有效 token轮换时先加新 token再滚动节点最后删旧 token。
### 中风险
1. **回源证书和 TLS 模式混乱**
proxy-ng 到后端如果走公网HTTP 明文会暴露请求内容和 API Key。
处理方式:回源使用 HTTPS。自签证书可以先落地但生产建议固定 CA 或证书指纹,避免 `proxy_ssl_verify off` 长期存在。
2. **SSE / 流式请求被 nginx 缓冲**
sub2api 代理模型 API 时存在流式响应。nginx 默认缓冲可能让流式变成攒包。
处理方式:代理路径关闭 `proxy_buffering`,并验证 SSE 逐块到达。
3. **节点流量配额耗尽**
多节点会把每个请求复制成“用户到节点 + 节点到后端”两段公网流量。
处理方式:上线前按日请求量、平均响应大小、流式比例估算月流量。
4. **多个节点证书签发和 DNS 切换顺序**
多 A 记录生效前,节点需要先能签发或加载证书。否则部分用户会命中 TLS 错误节点。
处理方式:先部署节点,逐个本地 `--resolve` 验证,再加入 DNS。
5. **把入口中转节点误用为账号代理节点**
如果把 proxy-ng 节点同时拿来做账号出口代理,入口线路优化、账号代理池、上游访问风险会混在一起,后续很难排障和扩容。
处理方式proxy-ng 节点只开放 80/443 和必要回源链路;账号代理池另建,不纳入 `proxy-ng/`
## 我可以完全完成的部分
在本仓库内可以完整交付:
- `proxy-ng/` 目录结构、架构说明和部署模板。
- proxy-ng nginx 配置模板。
- proxy-ng `.env` 模板。
- proxy-ng 节点安装脚本骨架。
- 后端入口网关 nginx/Caddy 配置模板。
- sub2api 配置变更说明:`server.trusted_proxies`、API Key ACL 可信转发开关。
- 账号代理池和 proxy-ng 的边界说明。
- 本地静态检查nginx 配置语法只能在目标机器上最终验证,但模板结构可以先审阅。
如果授权连接目标服务器,还可以完成:
- 在每台 proxy-ng VPS 安装 nginx、写入配置、启动服务。
- 在后端服务器配置入口网关、密钥校验、防火墙白名单。
- 端到端验证 `/health`、真实 IP、登录限流、SSE。
- 输出实际节点清单和回滚命令。
## 必须人工配置或确认的部分
- 域名 DNS 托管平台账号操作,尤其是添加多 A 记录、切 Cloudflare、开健康检查或 Load Balancing。
- proxy-ng 节点机器购买、系统初始化、SSH 权限授权。
- 后端服务器防火墙/云安全组放行规则确认。
- 生产密钥生成和保存位置确认。仓库只放模板,不提交真实 token。
- 是否只允许中国大陆访问,以及是否包含香港、澳门、台湾。
- 是否接受普通多 A 记录的故障窗口,还是一开始就购买/启用健康检查调度。
- 入口中转流量规模和节点带宽预算。
- 账号代理池使用哪个外部方案。该问题不由 proxy-ng 节点承担。
## 官方依据
- Cloudflare DNS 支持同名多个 A/AAAA 记录,但普通 DNS 记录不是健康检查调度:<https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/>
- Cloudflare 同名多个 A/AAAA 记录可用于简单负载均衡,但 CNAME 与 A/AAAA 不能同名混用:<https://developers.cloudflare.com/dns/manage-dns-records/troubleshooting/records-with-same-name/>
- Cloudflare Load Balancing 的 DNS 记录支持 A/AAAA/CNAME并按池健康状态和策略分发<https://developers.cloudflare.com/load-balancing/load-balancers/dns-records/>
- Cloudflare Health Checks / Load Balancing 可以探测源站健康,用于故障判断和摘除:<https://developers.cloudflare.com/health-checks/>
## 推荐落地顺序
1. 先部署一个 proxy-ng 节点,后端入口网关开启 IP 白名单和密钥校验。
2. 验证单节点链路:`/health`、真实 IP、登录限流、SSE、后端直连拒绝。
3. 增加第二个 proxy-ng 节点,但先不加入正式 DNS`--resolve` 指定节点 IP 验证入口。
4. 把多个节点加入 DNS多 A 记录先设低 TTL。
5. 如果出现随机失败或节点经常波动,再升级为带健康检查的 DNS/负载均衡。
## 目录说明
```text
proxy-ng/
├── README.md
├── env.example
├── nginx/
│ ├── proxy-node.conf.template
│ └── backend-gateway.conf.template
└── scripts/
└── install-proxy-node.sh
```