← 文档索引

Pangolin 控制面 TLS(Cloudflare Tunnel 前置)实现计划

2026-07-06 · 阅读版 · 执行真相源 docs/superpowers/plans/2026-07-06-control-plane-tls-tunnel.md(带 checkbox)

目标:把 pangolin-server 控制面 API 从明文 http://103.119.13.48:8080 迁到 https://api.yanmeiai.com,经 Cloudflare Tunnel 前置(隐藏源站 IP、白嫖标准 443 + 免证书)。 数据面 sing-box REALITY :443 全程不动。

架构

pangolin1 上跑 cloudflared 出站隧道(不监听任何入站端口 → 与 sing-box 独占的 :443 零冲突),CF 边缘把 api.yanmeiai.com 的请求经隧道回送到 127.0.0.1:8080。客户端(Flutter 四端共享 kApiBaseUrl)默认改 https 域名; 控制面下发给客户端 sing-box 的 .srs 规则集下载基址(PANGOLIN_PUBLIC_URL) 同步改 https。最后一步把 :8080 收回 loopback 并关防火墙,彻底退役明文口——该步有 上线顺序闸(须待现网客户端更新后再做)。

端口 / URL 布局

用途对外源站/绑定本轮变更
控制面 HTTP APIhttps://api.yanmeiai.com(CF Tunnel)127.0.0.1:8080新增 CF Tunnel 前置 + 收 loopback
数据面 sing-box REALITY:443(节点公网 IP)同端口不动
gRPC agent(mTLS)—(仅节点内):9443不动

全局约束

6 个任务

Task 1 · Cloudflare Tunnel 供给

Create: deploy/single-node/systemd/cloudflared.service · Modify: deploy/single-node/deploy.sh
CF 账户侧(cf-api)建 remotely-managed 隧道 + ingress(api.yanmeiai.comhttp://localhost:8080)+ 代理 CNAME;pangolin1 装 cloudflared(Debian apt 源)+ committed systemd unit(token 经 EnvironmentFile 注入,不入 unit 本体)。验证:https://api.yanmeiai.com/healthz 与旧的 http://103.119.13.48:8080/healthz 并存可用(加法,不破坏现网)。

Task 2 · 客户端控制面基址切 https + Android 去明文

Modify: client/lib/services/api_config.dart · client/android/.../AndroidManifest.xml · Create: client/test/unit/api_config_test.dart
先写守护测试(断言 kApiBaseUrl 必须 https:// 且不含节点 IP)→ 确认失败 → 把 kApiBaseUrl 默认值改为 https://api.yanmeiai.com(仍保留 String.fromEnvironment 可本地覆盖)→ 测试转绿。同步移除 Android manifest 的 android:usesCleartextTraffic="true"(控制面已 https,不再需要明文豁免;iOS/macOS 无 ATS 配置,无需改动)。跑 flutter analyze + 全量单测。

Task 3 · CI 守护:Android release manifest 禁明文

Create: ci/scan-cleartext.sh · Modify: .gitea/workflows/ci.yml
新增扫描脚本:manifest 一旦重新出现 usesCleartextTraffic="true" 就 CI 失败(防止将来有人把明文开关加回来,退回到 #25 之前的不安全态)。接入 ci.yml 新 job + shellcheck 列表。

Task 4 · PANGOLIN_PUBLIC_URL 切 https

Modify: deploy/single-node/deploy.sh
该变量被嵌进客户端 sing-box 配置当 .srs 分流规则集下载基址(clientconfig.go)。不改的话新客户端仍去明文 IP 拉。改为 https://api.yanmeiai.com;与 Task 1 隧道并存,对新旧客户端都安全(URL 由服务端下发,客户端只是照着 GET)。pangolin1 上应用 + 重启 server,验证规则集经隧道可 200 下载。

Task 5 · 退役明文口(收 loopback + 关防火墙 + 修健康检查)上线顺序闸

Modify: deploy/single-node/deploy.sh · scripts/ci/deploy-server.sh
此 Task 会切断外部 http://103.119.13.48:8080,只有当现网客户端都已更新到 Task 2 的 https 版本后才能执行,执行前需与用户确认「旧客户端可弃」。内容:ADDR127.0.0.1:8080;不再 ufw 放行 8080;deploy-server.sh 健康检查从「runner 远程 curl 公网 IP」改为「ssh 内本地 curl loopback」+「经隧道 curl https 域名」双路验证。验证:明文口不可达、隧道仍活、ss 显示 8080 仅监听 127.0.0.1

Task 6 · 文档更新(本任务)

Modify: CLAUDE.md · docs/index.html · docs/control-plane-tls-tunnel.html(本页)
CLAUDE.md 补充端口/URL 布局说明;生成本 HTML 阅读版并登记 docs/index.html「实现计划」分类;顺带修正 deploy/single-node/deploy.sh 摘要 echo 里残留的旧明文口描述(Task 4/5 落地后的措辞漂移)。

上线顺序

Task 1(隧道加法)→ Task 4(PANGOLIN_PUBLIC_URL,新旧客户端皆安全)→ Task 2(客户端切 https,发版)→ 待客户端更新 → Task 5(收口)。Task 3(CI 守护)、Task 6(文档)无顺序耦合,可随时并行推进。

不在本轮