sub2api/docs/agent-specs/2026-05-26-proxy-ng-origin加固-审阅版.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

36 KiB
Raw Permalink Blame History

proxy-ng origin 加固方案 — 审阅版

日期2026-05-26 状态已执行2026-05-26 有边界调整 适用范围:proxy.api.lilifamily.com 公开入口、catproxy.lilifamily.com 公开直连主站入口、origin.proxy.api.lilifamily.com 受限回源入口、*.proxy.api.lilifamily.com proxy-ng 节点扩展

2026-05-26 决策变更:catproxy.lilifamily.com 不再做 IP 白名单限制,作为 3c4g 公开直连主站域名和回滚入口;只有 origin.proxy.api.lilifamily.com 保持来源 IP 白名单和 X-Proxy-Ng-Token 校验。本文中早期关于 catproxy 受限访问的草案描述已被此决策覆盖,当前运行事实以 ops/remote/us-racknerd-0526-sub2api/ 为准。

1. 结论

当前 JPpro 入口中转已经可以用于稳定性测试,但还不是生产加固架构。后续不依赖 Cloudflare Load Balancing公开入口用普通 DNS 记录指向 proxy-ng 节点,防攻击和主站隐藏由 nginx、防火墙、origin 白名单和 token 完成。

当前已执行链路是:

flowchart LR
    U[用户] -->|HTTPS| P[公开入口<br/>proxy.api.lilifamily.com]
    P -->|HTTPS| J[JPpro nginx<br/>jp.proxy.api.lilifamily.com]
    J -->|HTTPS + 节点 Token| O[3c4g origin nginx<br/>origin.proxy.api.lilifamily.com]
    O -->|127.0.0.1:8080| S[Sub2API]
    C[直连用户] -->|HTTPS| D[3c4g nginx<br/>catproxy.lilifamily.com]
    D -->|127.0.0.1:8080| S

推荐生产加固链路是:

flowchart LR
    U[用户] -->|HTTPS| D[公开入口<br/>proxy.api.lilifamily.com<br/>普通多 A / 手工切换]
    D --> J[JPpro nginx<br/>jp.proxy.api.lilifamily.com]
    D --> N[其它 proxy-ng 节点<br/>*.proxy.api.lilifamily.com]
    J -->|HTTPS + 节点 Token| O[3c4g origin nginx<br/>origin.proxy.api.lilifamily.com]
    N -->|HTTPS + 节点 Token| O
    O -->|本机回环| S[Sub2API :8080]

    C[普通公网用户] -.->|403 / 拒绝| O
    X[未知服务器] -.->|IP 不在白名单| O

前置阶段先做域名迁移和入口角色调整:

  1. 公开服务入口保留为 proxy.api.lilifamily.com,但它不再指向 3c4g而是指向 proxy-ng 节点。
  2. 3c4g 原直连入口从 proxy.api.lilifamily.com 改为 catproxy.lilifamily.com,作为公开直连主站域名和回滚入口。
  3. DNS 增加 origin.proxy.api.lilifamily.com A 记录,指向 3c4g只给 proxy-ng 回源使用。
  4. 其它 proxy-ng 节点统一使用 <node>.proxy.api.lilifamily.com 命名。

第一阶段加固只建议做三件事:

  1. 在 3c4g 增加独立 origin 入口:origin.proxy.api.lilifamily.com
  2. origin 入口只允许 JPpro IP 访问,并校验 X-Proxy-Ng-Token
  3. JPpro 从回源公网主域名改为回源 origin 入口。
  4. proxy.api.lilifamily.com 的 A 记录只指向 proxy-ng 节点,不再暴露 3c4g。

这三项完成后proxy-ng 才从“能用的公网反代”升级成“信任边界清楚的入口中转”。

2. 当前已验证事实

项目 当前事实
JPpro 服务器 个人-JPpro-akile-0504-1c1g
JPpro 公网 IP 151.242.164.72
JPpro 入口域名 jp.proxy.api.lilifamily.com
JPpro 当前职责 只运行 nginx proxy-ng不运行 Sub2API、PostgreSQL、Redis、Caddy 或账号出口代理
JPpro 当前回源 测试期可临时回源 https://catproxy.lilifamily.com,加固后必须改为 https://origin.proxy.api.lilifamily.com
3c4g 服务器 个人-US-racknerd-0526-3c4g
公开服务入口域名 proxy.api.lilifamily.com,目标是普通多 A 指向 proxy-ng 节点
3c4g 公开直连主站域名 catproxy.lilifamily.com,不做 IP 白名单限制
3c4g origin 域名 origin.proxy.api.lilifamily.com,只给 proxy-ng 回源
3c4g 当前职责 nginx 反代到本机 Sub2API 127.0.0.1:8080
当前风险边界 直接回源公网主域名,尚未做独立 origin、后端来源 IP 白名单、X-Proxy-Ng-Token 校验

2.1 域名命名与 DNS 记录

本方案按以下域名边界规划:

域名 DNS 记录 角色 说明
proxy.api.lilifamily.com 多个 A -> proxy-ng 节点 IP 公开服务入口 不用 Cloudflare LB普通 DNS 多 A 或手工切换
catproxy.lilifamily.com A -> 216.45.59.243 3c4g 公开直连主站入口 可直接访问主站,也可作为 proxy-ng 故障时的回滚入口
origin.proxy.api.lilifamily.com A -> 216.45.59.243 3c4g 回源入口 只给 proxy-ng 节点访问,必须加 IP 白名单和 token
jp.proxy.api.lilifamily.com A -> 151.242.164.72 JPpro proxy-ng 节点 当前第一台入口中转节点
*.proxy.api.lilifamily.com 每个节点独立 A/AAAA 后续 proxy-ng 节点命名空间 例如 us.proxy.api.lilifamily.comsg.proxy.api.lilifamily.com

约束:

  • proxy.api.lilifamily.com 是用户看到的正式入口,但它只指向 proxy-ng 节点,不直接指向 3c4g。
  • catproxy.lilifamily.com 是独立公开直连入口proxy-ng 回源不使用它,也不应在 proxy.api.lilifamily.com 链路中把它暴露到 LocationHost、页面链接或错误页中。
  • *.proxy.api.lilifamily.com 在本文表示节点命名规则,不等于必须使用一条 wildcard A 记录。
  • 多个节点如果 IP 不同,应为每个节点创建独立 A/AAAA 记录;proxy.api.lilifamily.com 可以配置多个 A 记录,但这是普通 DNS 轮询,不具备健康检查和按网络质量调度能力。
  • origin.proxy.api.lilifamily.com 即使有公网 DNS也不应作为用户入口访问控制必须在 nginx 和防火墙层生效。
  • origin 默认限制公网访问,证书签发不应依赖长期开放 HTTP-01优先使用 DNS-01或在签发/续期窗口临时开放并立即恢复限制。catproxy 公开访问,可使用常规 HTTP-01。

当前配置留痕:

文件 说明
ops/remote/jppro-sub2api/README.md JPpro proxy-ng 部署记录
ops/remote/jppro-sub2api/current/nginx-jp-proxy-sub2api.conf JPpro 当前 nginx 配置副本
ops/remote/us-racknerd-0526-sub2api/current/nginx-sub2api.conf 3c4g 当前 nginx 主入口配置副本
docs/memorys/2026-05-25-proxy-ng职责边界.md proxy-ng 不承担账号出口代理的边界记录
proxy-ng/README.md 多节点 proxy-ng 方案说明
proxy-ng/nginx/proxy-node.conf.template proxy-ng 节点 nginx 模板
proxy-ng/nginx/backend-gateway.conf.template 后端入口网关模板

3. 目标和非目标

目标

  • 把用户公开入口和 proxy-ng 回源入口分离。
  • 让 3c4g 后端能识别“这是受控 proxy-ng 节点发来的请求”。
  • 防止普通公网用户绕过 proxy-ng 直接访问 origin。
  • 防止客户端伪造 X-Proxy-Ng-*X-Forwarded-* 头影响日志和安全判断。
  • 公开入口 proxy.api.lilifamily.com 只解析到 proxy-ng 节点,避免 3c4g 主站直接暴露。
  • 保留 catproxy.lilifamily.com 作为公开直连主站域名和紧急回滚入口。
  • 为后续新增 proxy-ng 节点提供标准流程。

非目标

  • 不把 JPpro 改造成账号出口代理。
  • 不在 proxy-ng 节点部署 Clash、sing-box、Xray、SOCKS、mixed 等代理服务。
  • 不改 Sub2API 业务代码作为第一阶段方案。
  • 不在仓库提交真实 token、.env、API key、数据库密码。
  • 不立即强制所有用户流量都走 JPpro。
  • 不立即建设复杂的多地域调度系统。

4. 设计项解释和实施方案

4.1 独立 origin 入口

作用

独立 origin 用来区分两类入口:

入口 面向对象 是否公开给用户
proxy.api.lilifamily.com 用户公开访问,解析到 proxy-ng 节点
catproxy.lilifamily.com 运维直连、临时回滚
origin.proxy.api.lilifamily.com proxy-ng 节点回源

如果 JPpro 继续回源 https://catproxy.lilifamily.com,那么 catproxy 就会被放进常规服务链路。它能用于短期迁移,但不能作为生产回源目标。生产回源必须使用 origin.proxy.api.lilifamily.com,并通过 IP 白名单和 token 限制访问。

独立 origin 的意义是:回源链路可以单独配置 IP 白名单、token 校验、日志格式和限流策略,不影响用户公开入口。

实施方案

DNS 增加:

proxy.api.lilifamily.com -> 151.242.164.72
proxy.api.lilifamily.com -> <其它 proxy-ng 节点 IP>
catproxy.lilifamily.com -> 216.45.59.243
origin.proxy.api.lilifamily.com -> 216.45.59.243

3c4g 新增 nginx server block

server {
    server_name origin.proxy.api.lilifamily.com;

    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/origin.proxy.api.lilifamily.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/origin.proxy.api.lilifamily.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host proxy.api.lilifamily.com;
        proxy_set_header X-Forwarded-Host $http_x_forwarded_host;
        proxy_set_header X-Forwarded-Proto https;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
        proxy_buffering off;
        proxy_request_buffering off;
    }
}

JPpro 后续改为:

proxy_pass https://origin.proxy.api.lilifamily.com;
proxy_ssl_server_name on;
proxy_ssl_name origin.proxy.api.lilifamily.com;
proxy_set_header Host origin.proxy.api.lilifamily.com;
proxy_set_header X-Forwarded-Host $host;

风险

  • 新增域名证书签发失败会导致 origin 不可用。
  • 如果直接切 JPpro 回源而未保留回滚,会造成 JPpro 入口不可用。

缓解

  • 先用 curl --resolve 验证 origin再切 JPpro。
  • JPpro 原配置保留备份;失败时把 proxy_pass 改回 https://catproxy.lilifamily.com

4.2 来源 IP 白名单

作用

来源 IP 白名单保证 origin 只接受你控制的 proxy-ng 节点访问。

即使别人知道 origin.proxy.api.lilifamily.com,只要请求来源 IP 不是 JPpro 或后续受控节点,就会被拒绝。

实施方案

3c4g origin nginx 增加:

location / {
    allow 151.242.164.72;   # JPpro
    deny all;

    proxy_pass http://127.0.0.1:8080;
}

如果服务器防火墙可控,建议同时在系统防火墙层限制:

允许 151.242.164.72 访问 443 或 origin 专用端口
拒绝其他公网来源访问 origin 入口

后续新增节点时,只追加节点 IP

allow 151.242.164.72;   # JPpro
allow x.x.x.x;          # 新 proxy-ng 节点
deny all;

风险

  • 节点 IP 写错会导致 proxy-ng 回源 403。
  • VPS 如果更换 IPorigin 会继续拒绝旧配置之外的来源。

缓解

  • 每个节点目录必须记录公网 IP。
  • 新增或迁移节点时,先更新 origin allowlist再切 DNS 或入口。

4.3 X-Proxy-Ng-Token

作用

IP 白名单证明“请求来自这台服务器 IP”但不能证明“请求一定来自你配置的 nginx”。

X-Proxy-Ng-Token 是第二道校验:

  • 防止同一节点上其他进程误打 origin。
  • 防止节点配置被部分滥用。
  • 为后续多节点密钥轮换提供边界。

正确边界是:

来源 IP 白名单 + X-Proxy-Ng-Token + HTTPS 回源

Token 不是防火墙替代品。

实施方案

JPpro 注入 token

proxy_set_header X-Proxy-Ng-Token "REDACTED_SECRET";
proxy_set_header X-Proxy-Ng-Node "jppro-akile-0504-1c1g";

3c4g origin 校验 token

map $http_x_proxy_ng_token $proxy_ng_token_ok {
    default 0;
    "REDACTED_SECRET" 1;
}

map $http_x_forwarded_host $sub2api_host {
    default $http_x_forwarded_host;
    "" "proxy.api.lilifamily.com";
}

server {
    server_name origin.proxy.api.lilifamily.com;

    location / {
        if ($proxy_ng_token_ok = 0) {
            return 403;
        }

        proxy_pass http://127.0.0.1:8080;
        proxy_set_header X-Proxy-Ng-Token "";
    }
}

真实 token 保存建议:

位置 规则
远程服务器 root-only 配置 可以保存真实 token权限建议 600
仓库 ops/remote/**/current/ 只保存脱敏副本
仓库 secrets/ 如需本机私有备份,必须被 .gitignore 排除

风险

  • 所有节点共用一个 token 时,泄露后需要同步更新所有节点。
  • nginx 配置中使用明文 token远程文件权限要控制好。

缓解

  • 第一阶段可以单 token。
  • 第二阶段支持双 token先加新 token再滚动节点最后删旧 token。
  • 真实 token 不写入 Git。

4.4 覆盖客户端伪造 header

作用

客户端可以自己发送这些 header

X-Proxy-Ng-Token
X-Proxy-Ng-Node
X-Forwarded-For
X-Real-IP
X-Forwarded-Host

如果 proxy-ng 不覆盖,后端日志和安全判断可能被伪造。

实施方案

JPpro 对安全相关 header 使用 proxy_set_header 覆盖:

proxy_set_header X-Proxy-Ng-Token "REDACTED_SECRET";
proxy_set_header X-Proxy-Ng-Node "jppro-akile-0504-1c1g";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Host $host;

3c4g origin 校验后清除 token不继续传给 Sub2API

proxy_set_header X-Proxy-Ng-Token "";
proxy_set_header X-Proxy-Ng-Node $http_x_proxy_ng_node;

风险

  • 如果 X-Forwarded-For 处理不当Sub2API 可能拿不到真实客户端 IP。
  • 如果信任任意 X-Forwarded-For,日志和限流可能被客户端伪造。

缓解

  • 第一阶段先让 JPpro 覆盖 X-Forwarded-For$remote_addr,保证不可伪造。
  • 后续如接入多级代理,再单独设计可信真实 IP 链路。

4.5 入口策略

作用

入口策略决定用户应该访问哪条链路。

如果同时存在多个入口但没有规则,会出现:

  • 有的用户走 JPpro。
  • 有的用户绕过 JPpro 直连 3c4g。
  • 出问题时无法快速判断是哪条链路坏了。

推荐阶段

阶段 入口策略 目的
P0 迁移期 catproxy.lilifamily.com 可短期直连,jp.proxy.api.lilifamily.com 用于测试中转 建立回滚入口
P1 加固期 JPpro 改走 origin + IP 白名单 + token 验证安全边界
P2 稳定期 proxy.api.lilifamily.com 多 A 指向 proxy-ng 节点 常规用户不直连 3c4g

实施方案

当前不依赖 Cloudflare LB。公开入口采用普通 DNS 多 A 或手工切换,接受“坏节点不会自动摘除”的限制。

先保持:

proxy.api.lilifamily.com      -> 一个或多个 proxy-ng 节点
jp.proxy.api.lilifamily.com   -> JPpro proxy-ng
*.proxy.api.lilifamily.com    -> 后续 proxy-ng 节点命名空间
origin.proxy.api.lilifamily.com -> 3c4g origin仅供 proxy-ng 回源
catproxy.lilifamily.com       -> 3c4g 受限直连/管理/回滚入口

稳定期约束:

proxy.api.lilifamily.com 不能解析到 3c4g
proxy-ng 节点不能把 catproxy.lilifamily.com 暴露给用户
catproxy.lilifamily.com 不能作为常规公开业务入口

4.6 监控

作用

proxy-ng 是多段链路。用户报慢或报错时,需要区分:

  • JPpro nginx 是否正常。
  • JPpro 到 3c4g origin 是否正常。
  • 3c4g nginx 是否正常。
  • Sub2API 是否正常。
  • 证书是否即将过期。

实施方案

最小监控项:

检查项 期望
https://jp.proxy.api.lilifamily.com/health 200
https://proxy.api.lilifamily.com/health 200,且解析到 proxy-ng 节点
https://catproxy.lilifamily.com/health 从管理 IP/Tailscale 访问 200
https://catproxy.lilifamily.com/health 从普通公网访问 403444
https://origin.proxy.api.lilifamily.com/health 从非白名单来源访问 403 或连接被拒绝
https://origin.proxy.api.lilifamily.com/health 从 JPpro 访问 200
POST /v1/responses 无授权访问 401 API_KEY_REQUIRED
证书剩余天数 小于 15 天告警
nginx 服务状态 非 active 告警

可以用 Uptime Kuma或先用 cron + webhook。

风险

  • 只监控 /health 不足以发现 API 路由问题。
  • 从本机监控 origin 可能因为 IP 白名单而得到 403这是预期不是故障。

缓解

  • 同时监控 /health 和未授权 API 路由。
  • origin 监控要从 JPpro 节点执行。

4.7 日志可观测

作用

响应慢时要知道慢在哪里。

关键区分:

字段 含义
request_time 当前 nginx 从接收请求到响应完成的总耗时
upstream_response_time 当前 nginx 等上游响应的耗时
upstream_status 上游返回状态,例如 200、401、502、504
X-Proxy-Ng-Node 哪个 proxy-ng 节点处理了请求
request_id 一次请求的追踪 ID

实施方案

JPpro 和 3c4g origin 都建议增加专用 log format

log_format proxy_ng '$remote_addr "$request" status=$status '
                    'request_time=$request_time '
                    'upstream_status=$upstream_status '
                    'upstream_time=$upstream_response_time '
                    'node=$sent_http_x_proxy_ng_node '
                    'request_id=$request_id';

access_log /var/log/nginx/proxy-ng-access.log proxy_ng;

风险

  • access log 过大导致磁盘占满。

缓解

  • 配置 logrotate。
  • 稳定后可只保留错误日志和采样日志。

4.8 无 Cloudflare LB 的防攻击方案

作用

不依赖 Cloudflare LB 后,公网攻击会直接打到 proxy-ng 节点。防攻击目标不是承诺抗大规模 DDoS而是降低常见扫描、CC、小流量洪泛、慢连接和暴力破解对服务的影响并保证攻击不会绕过 proxy-ng 打到 3c4g 主站。

API 网关类服务常见风险:

  • 大量并发连接。
  • 大请求体。
  • 慢速上传。
  • 登录和验证码接口被刷。
  • 流式响应占用长连接。
  • 路径扫描,例如 /.env/.git/wp-login.php
  • 直接扫描 3c4g IP、catproxyorigin

实施方案

第一层proxy-ng 节点系统防火墙。

入站允许:
- 80/tcp、443/tcp公网用户访问 proxy-ng
- 22/tcp只允许管理 IP 或 Tailscale/内网管理入口

入站拒绝:
- 其它所有端口
- 1080、7890、mixed、socks、xray、sing-box 等出口代理端口

第二层proxy-ng 节点 nginx 基础抗压。

worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 4096;
    multi_accept on;
}

http {
    sendfile on;
    tcp_nopush on;
    reset_timedout_connection on;

    keepalive_timeout 20s;
    keepalive_requests 100;
    client_header_timeout 10s;
    client_body_timeout 30s;
    send_timeout 30s;

    client_max_body_size 100m;
    client_body_buffer_size 256k;
    large_client_header_buffers 4 16k;

    limit_conn_zone $binary_remote_addr zone=conn_per_ip:20m;
    limit_req_zone $binary_remote_addr zone=req_per_ip:20m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=auth_per_ip:10m rate=10r/m;
}

第三层proxy-ng 节点 nginx 路由限流。

location ~ /\.(git|svn|hg|env|aws|ssh) {
    return 444;
}

location ~* ^/(wp-admin|wp-login\.php|phpmyadmin|cgi-bin|vendor|boaform) {
    return 444;
}

location / {
    limit_req zone=req_per_ip burst=30 nodelay;
    limit_conn conn_per_ip 50;

    proxy_pass https://origin.proxy.api.lilifamily.com;
}

location ~ ^/api/v1/auth/(login|login/2fa|register|send-verify-code|forgot-password|reset-password) {
    limit_req zone=auth_per_ip burst=3 nodelay;
    limit_conn conn_per_ip 10;

    proxy_pass https://origin.proxy.api.lilifamily.com;
}

第四层3c4g origin 防绕过。

3c4g 防火墙:
- 只允许 proxy-ng 节点 IP 访问 origin 入口端口
- 只允许管理 IP 或 Tailscale 访问 SSH
- Sub2API 8080 只监听 127.0.0.1 或 Docker 内网,不直接暴露公网

3c4g nginx
- origin server 只 allow proxy-ng 节点 IP
- 必须校验 X-Proxy-Ng-Token
- default_server 对未知 Host 返回 444
- catproxy 入口只用于受限直连/回滚,不作为公开业务入口

第五层fail2ban 和日志轮转。

fail2ban 建议规则:
- nginx-404短时间大量 404/444 扫描封禁
- nginx-limit-req短时间大量 429 封禁
- sshdSSH 暴力破解封禁

logrotate
- nginx access/error 日志按大小轮转
- 保留 3-7 份
- 防止攻击流量把磁盘写满

第六层Sub2API 成本保护。

- API Key 配额和余额限制
- 单 key 并发限制
- 单 key 速率限制
- 异常 401/429/5xx 告警
- 高额模型调用成本预警

风险

  • 这些措施不能替代专业 DDoS 清洗;大流量打满 VPS 带宽时仍会不可用。
  • 太严格会误伤正常 API 客户端。
  • 流式响应连接时间长,连接数限制过低会误伤。
  • 多 A 普通 DNS 没有健康摘除;坏节点仍可能被解析到。

缓解

  • 先在 JPpro 测试入口启用。
  • 观察 429 和连接拒绝日志后再调参。
  • /v1/responses 等长连接路径不要过度收紧。
  • proxy.api.lilifamily.com TTL 设低,例如 60-300 秒,故障时手工删除坏节点 A 记录。
  • 保留至少一个受限直连回滚入口,但不公开给普通用户。

4.9 备份和回滚

作用

proxy-ng 节点无业务数据,真正不能丢的是 3c4g 的数据库、Redis、Sub2API 数据目录和运行配置。

入口改造前必须有回滚方案,否则一次 nginx 配置错误可能导致入口不可用。

实施方案

改动前备份:

3c4g:
- /etc/nginx/sites-available/sub2api.conf
- /etc/nginx/sites-enabled/sub2api.conf
- /opt/sub2api/docker-compose.yml
- /opt/sub2api/.env
- PostgreSQL dump
- /opt/sub2api/data

JPpro:
- /etc/nginx/sites-available/jp-proxy-sub2api.conf
- /etc/nginx/conf.d/proxy-ng-map.conf

回滚路径:

故障 回滚方式
origin 配置失败 JPpro proxy_pass 改回 https://catproxy.lilifamily.com
token 校验误拦截 临时关闭 origin token 校验,恢复后重新加固
IP 白名单误拦截 修正 allow 节点 IP 或临时回滚到公网主入口
JPpro 故障 用户切回 https://catproxy.lilifamily.com
3c4g 服务异常 使用 3c4g 备份和 Docker Compose 回滚

4.10 多节点扩展

作用

多节点用于提升入口稳定性,但不是简单“节点越多越好”。

不使用 Cloudflare LB 时,多 A 记录会把用户随机分配到节点。某个节点故障后DNS 仍可能返回坏 IP表现为部分用户随机失败。

实施方案

新增节点标准流程:

1. 新建 ops/remote/<server>-sub2api/
2. 安装 nginx + certbot
3. 配置 proxy-ng node id
4. 回源 origin.proxy.api.lilifamily.com
5. 3c4g origin allow 新节点 IP
6. 给新节点配置 token
7. 验证 /health、/、/v1/responses
8. 加入 `proxy.api.lilifamily.com` 多 A 记录

DNS 策略:

阶段 方案 风险
P0 单节点入口 简单,但节点故障需手工切换
P1 proxy.api.lilifamily.com 多 A 记录TTL 60-300 秒 成本低,但坏节点不会自动摘除
P2 自建监控 + 手工或脚本更新 DNS 不依赖 Cloudflare LB但需要自己处理摘除

当前确认不采用 Cloudflare Load Balancing因此方案不承诺按用户网络质量或节点健康自动调度。节点健康只能通过监控告警后手工移除 DNS 记录,或后续自建 DNS 更新脚本实现。

5. 推荐实施顺序

阶段 0主站隐藏和入口域名迁移基线

先把公开入口和 3c4g 直连入口拆开,避免 proxy-ng 节点或公开 DNS 暴露主站。

动作:

  1. proxy.api.lilifamily.com 从 3c4g 移走,改为 A 到 proxy-ng 节点,例如 JPpro。
  2. DNS 增加或确认 catproxy.lilifamily.com -> 216.45.59.243,但它只作为受限直连、管理和回滚入口。
  3. 3c4g nginx 为 catproxy.lilifamily.com 签发证书,但访问限制为管理 IP、Tailscale 或临时回滚窗口。
  4. Sub2API 对外公开域名应保持为用户访问入口 proxy.api.lilifamily.com,避免页面、回调或错误信息暴露 catproxy.lilifamily.com
  5. JPpro 临时回源可用 https://catproxy.lilifamily.com,但只作为切 origin 前的过渡。

目标基线链路:

proxy.api.lilifamily.com -> JPpro/proxy-ng -> catproxy.lilifamily.com(临时) -> 3c4g -> Sub2API

验收:

  • proxy.api.lilifamily.com/health 返回 200且解析到 proxy-ng 节点 IP。
  • jp.proxy.api.lilifamily.com/health 返回 200。
  • jp.proxy.api.lilifamily.com/ 返回 200。
  • 普通公网访问 catproxy.lilifamily.com 被拒绝,或仅在明确回滚窗口内允许。
  • 未授权 POST /v1/responses 返回 401。

阶段 13c4g 增加 origin

动作:

  1. DNS 增加 origin.proxy.api.lilifamily.com -> 216.45.59.243
  2. 3c4g nginx 新增 origin server block。
  3. certbot 为 origin 域名签发证书。
  4. 暂不切 JPpro先验证 origin 本身。

验收:

  • 从 3c4g 本机访问 127.0.0.1:8080/health 正常。
  • 从 JPpro 访问 https://origin.proxy.api.lilifamily.com/health 正常。
  • 从非白名单来源访问 origin 被拒绝。

阶段 2origin 加 IP 白名单和 token

动作:

  1. 3c4g origin 允许 JPpro IP 151.242.164.72
  2. 3c4g origin 配置 X-Proxy-Ng-Token 校验。
  3. JPpro 配置注入 token。
  4. token 真实值只保存在远程 root-only 配置。

验收:

  • JPpro 带 token 访问 origin 返回 200。
  • JPpro 不带 token 访问 origin 返回 403。
  • 非 JPpro IP 访问 origin 返回 403 或连接拒绝。
  • origin 不把 X-Proxy-Ng-Token 继续传给 Sub2API。

阶段 3JPpro 切换 origin 回源

动作:

  1. 备份 JPpro 当前 nginx 配置。
  2. JPpro proxy_passhttps://catproxy.lilifamily.com 改为 https://origin.proxy.api.lilifamily.com
  3. nginx -t 后 reload。
  4. 公网验证 JPpro 入口。

验收:

  • https://jp.proxy.api.lilifamily.com/health 返回 200。
  • https://jp.proxy.api.lilifamily.com/ 返回 200。
  • 未授权 POST /v1/responses 返回 401。
  • 3c4g origin access log 能看到 X-Proxy-Ng-Node=jppro-akile-0504-1c1g

阶段 4完善监控、日志、限流

动作:

  1. 增加 proxy-ng 专用 access log。
  2. 配置证书到期检查。
  3. 配置 JPpro 和 3c4g 健康检查。
  4. 先在 JPpro 入口启用保守限流、连接数限制和扫描路径拦截。
  5. 配置 fail2ban 和 logrotate。
  6. 3c4g 防火墙确认只允许 proxy-ng 节点访问 origin。

验收:

  • 能通过日志区分 JPpro 耗时和 3c4g origin 耗时。
  • 证书剩余天数低于阈值能告警。
  • 429 数量可观测,不误伤正常请求。
  • 访问 /.env/.git/config/wp-login.php 等扫描路径返回 444 或 403。
  • 3c4g 8080 不对公网开放。

阶段 5评估是否增加第二个 proxy-ng 节点

动作:

  1. 选择第二台节点。
  2. 按同样目录规范留痕。
  3. 先不进正式 DNS--resolve 验证。
  4. 通过 --resolve proxy.api.lilifamily.com:443:<节点IP> 逐个验证。
  5. 验证通过后加入 proxy.api.lilifamily.com 多 A 记录。

验收:

  • 第二节点独立验证通过。
  • origin allowlist 已补第二节点 IP。
  • 节点配置副本已保存到项目 ops/remote/<server>-sub2api/
  • proxy.api.lilifamily.com 的多 A 记录不包含 3c4g IP。

6. 配置草案

6.1 3c4g origin nginx 草案

map $http_x_proxy_ng_token $proxy_ng_token_ok {
    default 0;
    "REDACTED_SECRET" 1;
}

map $http_x_forwarded_host $sub2api_host {
    default $http_x_forwarded_host;
    "" "proxy.api.lilifamily.com";
}

server {
    server_name origin.proxy.api.lilifamily.com;

    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/origin.proxy.api.lilifamily.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/origin.proxy.api.lilifamily.com/privkey.pem;

    server_tokens off;
    underscores_in_headers on;
    client_max_body_size 100m;

    location / {
        allow 151.242.164.72;
        deny all;

        if ($proxy_ng_token_ok = 0) {
            return 403;
        }

        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $sub2api_host;
        proxy_set_header X-Real-IP $http_x_real_ip;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-Host $http_x_forwarded_host;
        proxy_set_header X-Proxy-Ng-Token "";
        proxy_set_header X-Proxy-Ng-Node $http_x_proxy_ng_node;
        proxy_redirect https://origin.proxy.api.lilifamily.com/ https://$sub2api_host/;
        proxy_redirect https://catproxy.lilifamily.com/ https://$sub2api_host/;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
        proxy_buffering off;
        proxy_request_buffering off;
    }
}

待审阅点:X-Real-IPX-Forwarded-For 是否按第一阶段“不可伪造优先”处理,还是按“保留真实客户端 IP 链路”处理。当前草案偏向保留链路,但需要结合 Sub2API 的 trusted_proxies 配置验证。

6.2 JPpro nginx 草案

server {
    server_name proxy.api.lilifamily.com jp.proxy.api.lilifamily.com;

    server_tokens off;
    underscores_in_headers on;
    client_max_body_size 100m;

    add_header X-Proxy-Ng-Node "jppro-akile-0504-1c1g" always;

    location / {
        proxy_pass https://origin.proxy.api.lilifamily.com;
        proxy_ssl_server_name on;
        proxy_ssl_name origin.proxy.api.lilifamily.com;
        proxy_http_version 1.1;

        proxy_set_header Host origin.proxy.api.lilifamily.com;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Proxy-Ng-Node "jppro-akile-0504-1c1g";
        proxy_set_header X-Proxy-Ng-Token "REDACTED_SECRET";

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
        proxy_buffering off;
        proxy_request_buffering off;
    }
}

待审阅点:当前 JPpro 配置已有 client_max_body_size 256m,草案写 100m 是为了和 3c4g 主入口一致。是否保留 256m 需要根据实际请求体规模确认。

6.3 3c4g catproxy 受限直连草案

catproxy.lilifamily.com 不作为常规用户入口。它的作用是运维验证和紧急回滚,因此默认应限制来源。

server {
    server_name catproxy.lilifamily.com;

    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/catproxy.lilifamily.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/catproxy.lilifamily.com/privkey.pem;

    server_tokens off;
    underscores_in_headers on;
    client_max_body_size 100m;

    # 管理 IP、Tailscale 出口或临时回滚窗口内的来源。
    allow <ADMIN_OR_TAILSCALE_IP>;
    deny all;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host proxy.api.lilifamily.com;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-Host proxy.api.lilifamily.com;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
        proxy_buffering off;
        proxy_request_buffering off;
    }
}

server {
    listen 443 ssl default_server;
    server_name _;
    return 444;
}

如果管理 IP 不固定,优先使用 Tailscale、SSH 隧道或临时开放窗口,不建议长期把 catproxy.lilifamily.com 暴露给公网。

7. 验收清单

7.1 基础链路

  • https://proxy.api.lilifamily.com/health 返回 200且 DNS 解析结果只包含 proxy-ng 节点 IP。
  • 从管理 IP/Tailscale 访问 https://catproxy.lilifamily.com/health 返回 200。
  • https://jp.proxy.api.lilifamily.com/health 返回 200。
  • https://jp.proxy.api.lilifamily.com/ 返回 200。
  • 未授权 POST https://jp.proxy.api.lilifamily.com/v1/responses 返回 401 API_KEY_REQUIRED
  • 普通公网访问 https://catproxy.lilifamily.com/ 返回 403/444除非处于明确回滚窗口。

7.2 origin 边界

  • JPpro 带 token 访问 https://origin.proxy.api.lilifamily.com/health 返回 200。
  • JPpro 不带 token 访问 origin 返回 403。
  • 非 JPpro IP 访问 origin 返回 403 或连接被拒绝。
  • origin 日志能看到 X-Proxy-Ng-Node
  • origin 不把 X-Proxy-Ng-Token 继续传给 Sub2API。

7.3 回滚验证

  • JPpro 配置可一条改回 proxy_pass https://catproxy.lilifamily.com
  • 3c4g 受限入口 catproxy.lilifamily.com 对管理 IP/Tailscale 可访问,对普通公网不可访问。
  • 远程配置备份路径已记录。

7.4 运维验证

  • nginx -t 通过。
  • systemctl is-active nginx 返回 active
  • 证书到期时间已记录。
  • 访问日志可区分 request_timeupstream_response_time
  • 限流启用后没有误伤正常 API 请求。
  • /.env/.git/config/wp-login.php 等扫描路径返回 444/403。
  • fail2ban 对高频 404/429 和 SSH 爆破生效。
  • logrotate 已限制 nginx 日志增长。
  • proxy.api.lilifamily.com 的任一 A 记录故障时,有手工摘除流程。

8. 风险和取舍

风险 严重性 原因 缓解
origin 配置错误导致 JPpro 入口不可用 JPpro 切到 origin 后依赖新链路 先验证 origin再切 JPpro保留回滚
IP 白名单误配 节点 IP 写错或 VPS 换 IP 操作前核对公网 IP变更留痕
token 泄露 nginx 远程配置含明文 token 权限 600;仓库只保存脱敏副本
真实客户端 IP 丢失 为防伪造而覆盖 X-Forwarded-For 明确第一阶段优先级;后续再做可信 IP 链路
限流误伤正常请求 API 客户端并发高、流式请求长 先保守配置并观察日志
大流量 DDoS 打满 proxy-ng 带宽 不使用 Cloudflare LB/清洗时,攻击流量直达 VPS 接受该边界;多节点分散;必要时换高防/CDN
catproxy 被公网发现并直接访问 3c4g 直连入口暴露会绕过 proxy-ng 默认 deny all仅管理 IP/Tailscale/临时回滚允许
多 A 记录随机命中坏节点 普通 DNS 无健康检查 TTL 60-300 秒;监控告警后手工摘除坏 A 记录
日志占满磁盘 access log 增多 配置 logrotate 或采样

9. 待确认项

  • 公开服务入口采用 proxy.api.lilifamily.com,但只解析到 proxy-ng 节点。
  • catproxy.lilifamily.com 作为 3c4g 受限直连、管理和紧急回滚入口。
  • origin 回源入口采用 origin.proxy.api.lilifamily.com
  • proxy-ng 节点统一使用 <node>.proxy.api.lilifamily.com 命名。
  • 不依赖 Cloudflare Load Balancingproxy.api.lilifamily.com 使用普通 A 记录指向 proxy-ng 节点。
  • catproxy.lilifamily.com 的长期访问策略:仅 Tailscale/管理 IP还是完全不开放公网。
  • JPpro 到 origin 是否继续使用 443还是改用 origin 专用端口。
  • 第一阶段是否优先保证 X-Forwarded-For 不可伪造,接受真实客户端 IP 链路暂时简化。
  • token 采用单 token 还是一开始就做双 token 轮换。
  • 是否立即启用限流、fail2ban、扫描路径 444还是先只增强 origin 安全边界。
  • 监控使用 Uptime Kuma、cron + webhook还是暂时手工巡检。
  • 下一台 proxy-ng 节点是否已经确定。

10. 下一步

建议先审阅并确认以下决策:

  1. origin 域名和是否使用 443。
  2. JPpro 回源切换窗口和回滚策略。
  3. X-Forwarded-For 第一阶段处理策略。
  4. token 保存位置和轮换方式。

确认后再输出执行版文档,执行版应包含:

  • 远程配置文件路径。
  • 备份命令。
  • 变更步骤。
  • 验证命令。
  • 回滚命令。
  • 本地 ops/remote/ 留痕更新清单。