sub2api/docs/agent-specs/2026-05-21-国际互联网络优化-执行版.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

10 KiB
Raw Permalink Blame History

国际互联网络优化 — 执行版

日期2026-05-21 | 前置:审阅版已通过

1. 目标与范围

在 1C/1G 轻量 VPS 上部署 nginx 反向代理,通过 Cloudflare CDN 实现中国 IP 白名单访问控制,将流量转发到后端 2C4G 高性能服务器的 sub2api 服务。

2. 前置假设

  • 轻量 VPS 已就绪OS Debian/Ubuntu有公网 IP已配置 SSH 密钥登录
  • 高性能服务器已部署 sub2apiDocker Compose监听 8080config.yaml 可编辑
  • 域名 proxyapi.cyan2000.uk 的 NS 管理权限在手
  • 两台 VPS 之间通过公网 IP 通信(无内网)
  • 目标用户全部在中国大陆(+ 酌情香港/澳门)
  • Cloudflare 免费计划账户已注册

3. 涉及文件与路径

轻量 VPS新部署

路径 操作 说明
/etc/nginx/nginx.conf 写入 主配置,定义 upstream、限流区域
/etc/nginx/ssl/fullchain.pem certbot 签发 Let's Encrypt 证书
/etc/nginx/ssl/privkey.pem certbot 签发 私钥
/etc/systemd/system/nginx.service.d/override.conf 创建 MemoryMax + Restart
/etc/fail2ban/jail.local 写入 nginx-404 + nginx-limit-req 规则
/etc/fail2ban/filter.d/nginx-404.conf 写入 404 扫描过滤
/usr/local/bin/nginx-defense.sh 创建 内存压力自动降级
/usr/local/bin/cf-iptables.sh 创建 CF IP 白名单更新
/usr/local/bin/rebuild-nginx.sh 创建 一键重建
/etc/cron.d/cf-iptables 写入 每日 3:00 执行
/etc/cron.d/nginx-defense 写入 每分钟执行

高性能服务器(配置变更)

路径 操作 说明
config.yaml 编辑 server.trusted_proxies 加 nginx IP
config.yaml 编辑(条件) security.trust_forwarded_ip_for_api_key_acl: true
/etc/ssl/private/sub2api-key.pem 生成 回源自签证书私钥
/etc/ssl/certs/sub2api-cert.pem 生成 回源自签证书
docker-compose.yml 编辑(可选) nginx sidecar 做 TLS 终止

4. 数据流与依赖

用户浏览器
  │ HTTPS 443 (Let's Encrypt)
  ▼
Cloudflare CDN
  │ 加头: CF-Connecting-IP, CF-IPCountry
  │ HTTPS 443 (Let's Encrypt)
  ▼
轻量VPS nginx (1C/1G)
  │ iptables: 仅接受 CF IP 段
  │ nginx: CF-IPCountry 非 CN → 403
  │ 加头: X-Real-IP, X-Forwarded-For
  │ HTTPS 8443 (自签证书)
  ▼
后端 nginx sidecar (TLS 终止)
  │ HTTP :8080
  ▼
sub2api (Gin)
  │ ip.GetClientIP() → CF-Connecting-IP → X-Real-IP → X-Forwarded-For
  ▼
PostgreSQL / Redis

依赖:

  • 轻量 VPS → 后端公网 IP 可达(防火墙允许 8080 或 8443
  • 后端 → Redis / PostgreSQL已有
  • 轻量 VPS → cloudflare.comcron 拉取 IP 段)

5. 接口契约与字段变化

sub2api 配置变化

# config.yaml 新增
server:
  trusted_proxies:
    - "<轻量VPS公网IP>"
    - "173.245.48.0/20"     # Cloudflare IP 段(如需)
    # ... 或信任所有 CF IP 段

# 如果启用了 API Key IP 白名单功能
security:
  trust_forwarded_ip_for_api_key_acl: true

nginx 向下游传递的头

头名称 值来源 用途
X-Real-IP $remote_addrCF 边缘 IP 传统兼容
X-Forwarded-For $proxy_add_x_forwarded_for 代理链
X-Forwarded-Proto $schemehttps 协议感知
CF-Connecting-IP $http_cf_connecting_ipCF 原始头) sub2api 优先读取
Host $hostproxyapi.cyan2000.uk 虚拟主机

sub2api IP 解析优先级(ip.go 已有,不变)

CF-Connecting-IP → X-Real-IP → X-Forwarded-For(第一个公网IP) → c.ClientIP()

c.ClientIP()(限流器使用)仅在 trusted_proxies 含来源 IP 时才信任转发头。必须配置

6. 边界情况与失败路径

场景 预期行为
用户绕过 CF 直连源站 IP iptables DROP连接超时
用户通过 CF 但伪造 CF-IPCountry 头 CF 会覆盖此头或剥离nginx 看到空 → 403
用户通过 CF 但来自非中国 IP CF WAF Block第一层nginx $http_cf_ipcountry != CN → 403第二层
CF IP 段更新iptables 未同步 受影响的新 CF IP 回源被 DROP用户看到 502每日 cron 最小化窗口
轻量 VPS OOM systemd MemoryMax=800M 杀 nginx 而非全机 OOMRestart=always 5s 恢复
轻量 VPS 彻底宕机 备机 DNS 切换;或一键重建脚本
后端 502/504 nginx 返回 502 给用户;proxy_next_upstream error timeout http_502 有限重试
sub2api trusted_proxies 未配 限流器把所有用户视为同一 IPnginx IP共享限流桶
CF-Connecting-IP 传递失败nginx 没透传) sub2api 回退到 X-Forwarded-For 解析,仍能拿到真实 IP
Let's Encrypt 证书过期 certbot renew 自动续期;需确保 80 端口可访问用于验证
前端磁盘满 access_log 生产环境关掉error_log logrotate maxsize 50M

7. 实施步骤

第一阶段:后端配置(零中断)

  1. 登录高性能服务器
  2. 确认 config.yaml 路径,备份后编辑:
    server:
      trusted_proxies:
        - "<轻量VPS公网IP>"
    
  3. 生成自签证书:
    openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
      -keyout /etc/ssl/private/sub2api-key.pem \
      -out /etc/ssl/certs/sub2api-cert.pem \
      -subj "/CN=<后端公网IP>"
    
  4. docker-compose.yml 中添加 nginx sidecar 做 TLS 终止(监听 8443 → 转发 8080或直接用 sub2api 的 HTTPS 配置
  5. 重启 sub2api / Docker Compose
  6. 验证:curl --noproxy '*' -k https://<后端公网IP>:8443/health 返回 200

第二阶段Cloudflare DNS可能中断 1-2 分钟)

  1. 在 Cloudflare 添加站点 proxyapi.cyan2000.uk
  2. 将域名 NS 改为 Cloudflare 分配的 NS
  3. 等 NS 生效后,添加 DNS 记录A @ → 轻量 VPS 公网 IP橙色云朵开启
  4. SSL/TLS 模式设为 Full (strict)
  5. WAF 规则:(ip.geoip.country eq "CN") → Allow新建规则
  6. 验证:curl -H "Host: proxyapi.cyan2000.uk" https://<轻量VPS_IP>/health --resolve proxyapi.cyan2000.uk:443:<轻量VPS_IP> — 此时 nginx 还没配,先确认 CF 能到 VPS

第三阶段:轻量 VPS 部署

按顺序执行:

# 1. 基础软件
apt update && apt install -y nginx certbot fail2ban iptables-persistent

# 2. 获取证书(先关 nginx 80/443或 certbot standalone 模式)
certbot certonly --standalone -d proxyapi.cyan2000.uk

# 3. 写入 /etc/nginx/nginx.conf见附录 A

# 4. 写入 systemd override见附录 B
mkdir -p /etc/systemd/system/nginx.service.d

# 5. 写入 fail2ban 配置(见附录 C

# 6. 写入脚本(见附录 D
# - /usr/local/bin/cf-iptables.sh
# - /usr/local/bin/nginx-defense.sh
# - /usr/local/bin/rebuild-nginx.sh

# 7. 执行 iptables 白名单(先 accept 所有,确认 nginx 正常后再启用 DROP
bash /usr/local/bin/cf-iptables.sh

# 8. cron
echo "0 3 * * * root /usr/local/bin/cf-iptables.sh" > /etc/cron.d/cf-iptables
echo "* * * * * root /usr/local/bin/nginx-defense.sh" > /etc/cron.d/nginx-defense

# 9. 关闭 access_log生产环境
# 编辑 nginx.conf: access_log off;
# 或保留但 logrotate: maxsize 50M rotate 3

# 10. 启动
systemctl daemon-reload
systemctl enable --now nginx fail2ban

第四阶段:端到端验证

见第 8 节验证清单。

8. 测试与验证

自动化测试

# 1. 基本连通性
curl -I https://proxyapi.cyan2000.uk/health
# 预期: 200 OK

# 2. 中国 IP 访问控制 (CF-IPCountry 头)
curl -I https://proxyapi.cyan2000.uk/ -H "CF-IPCountry: CN"
# 预期: 正常转发,非 403
curl -I https://proxyapi.cyan2000.uk/ -H "CF-IPCountry: US"
# 预期: 403 Forbidden
curl -I https://proxyapi.cyan2000.uk/
# 预期: 403 (CF-IPCountry 为空 = 直连)

# 3. 压力测试 — 限流
ab -n 200 -c 50 https://proxyapi.cyan2000.uk/health
# 预期: 部分请求返回 429 / 503

# 4. Slowloris 抗性
slowhttptest -c 50 -H -u https://proxyapi.cyan2000.uk/
# 预期: 连接不耗尽,正常请求仍能响应

# 5. 源站 IP 直连
curl -I --connect-timeout 5 https://<轻量VPS_IP>/
# 预期: 超时或被拒绝 (iptables DROP)

# 6. 限流验证 — 真实 IP
for i in $(seq 1 35); do
  curl -s -o /dev/null -w "%{http_code}\n" https://proxyapi.cyan2000.uk/auth/login
done
# 预期: 前 20 个 200/401后续 429

验证清单

  • curl https://proxyapi.cyan2000.uk/health → 200
  • CF 关闭橙色云朵(直连 VPSCF-IPCountry 为空 → 403
  • CF-IPCountry: US → 403
  • CF-IPCountry: CN → 正常转发
  • sub2api 访问日志 client_ip = 真实用户 IP查看日志验证
  • auth 限流:同 IP 超频返回 429不同 IP 独立计数
  • 流式 API SSE 逐块到达
  • 源站 IP 直连超时
  • ab 压测限流生效
  • slowhttptest 连接不耗尽
  • fail2ban-client status 正常
  • systemctl show nginx | grep RestartRestart=always
  • systemctl show nginx | grep MemoryMaxMemoryMax=838860800
  • nginx error_log 无异常

9. 回滚 / 降级

快速回滚 DNS

  1. Cloudflare DNS 关闭 A 记录橙色云朵(变灰色 = DNS only
  2. 或将 A 记录直接指向后端服务器 IP绕过轻量 VPS

回滚 sub2api 配置

# 注释掉 trusted_proxies 行,恢复原状
# 重启 sub2api
docker compose restart

轻量 VPS 紧急降级

如果 nginx 出现异常但 iptables 正常:

# 紧急放行所有流量
iptables -F CF-WHITELIST
iptables -A CF-WHITELIST -j ACCEPT
# 重启 nginx
systemctl restart nginx

附录 Anginx 主配置

NETWORK_OPTIMIZATION.md 3.2 节完整配置。

附录 Bsystemd override

# /etc/systemd/system/nginx.service.d/override.conf
[Service]
Restart=always
RestartSec=5s
OOMScoreAdjust=-500
MemoryMax=800M
MemoryHigh=700M

附录 Cfail2ban 配置

# /etc/fail2ban/jail.local
[nginx-404]
enabled  = true
port     = http,https
filter   = nginx-404
logpath  = /var/log/nginx/access.log
maxretry = 30
findtime = 60
bantime  = 600

[nginx-limit-req]
enabled  = true
port     = http,https
filter   = nginx-limit-req
logpath  = /var/log/nginx/error.log
maxretry = 5
findtime = 60
bantime  = 600
# /etc/fail2ban/filter.d/nginx-404.conf
[Definition]
failregex = ^<HOST> -.*"(GET|POST|HEAD).*" 404
ignoreregex =

附录 D脚本

NETWORK_OPTIMIZATION.md 3.4 节:

  • cf-iptables.sh — CF IP 白名单(含 IPv6
  • nginx-defense.sh — 内存压力自动降级
  • rebuild-nginx.sh — 一键重建