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.
208 lines
9.5 KiB
Markdown
208 lines
9.5 KiB
Markdown
# 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
|
||
```
|