dpl/docs/maintenance/NODE_ONBOARDING.md

143 lines
16 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.

# 节点与订阅网关接入
核对日期:2026-10-11。本文是后续新增 dpl 节点的执行入口。首节点部署、服务器侧完整订阅联网与正式套餐开放已完成;用户明确要求跳过本地连通测试。Cloudflare 后台 TLS 后验和显式缓存规则仍受浏览器权限阻塞,整体尚未全部完成。凭据、机器令牌、用户 UUID 与订阅令牌只存受保护文件,不写入本文或 Git。
## 当前连接关系
订阅:客户端 → c2.deeplink-subscribe.com(Cloudflare 橙云 HTTPS)→ gateway-01 宿主 Nginx → dpl 独立 SubSieve → dpl 面板。
流量:客户端 → haiwi.lshan.eu.org:47101 → node-us01 64.44.115.18:24443 → 目标网络。AnyTLS 使用 us01.deeplink-subscribe.com 的有效证书,订阅要求严格校验。普通 Cloudflare 橙云只用于订阅 HTTP,不用于原生 AnyTLS 流量。
| 资源 | 本次新增 | 必须保留的原有资源 |
| --- | --- | --- |
| node-us01 | dpl-node,TCP 24443,机器/节点 ID 1 | XrayR,TCP 443 |
| 中转 | dpl-us01-anytls,47101 → 24443 | us01,46101 → 443;其他规则 |
| gateway-01 | dpl-subscribe-gateway、dpl-subscribe-admin | subscribe-gateway、subscribe-admin |
| 网关回环端口 | 18080 / 18443,管理 16444 | 8080 / 8443,管理 64444 |
| Docker 存储 | dpl_sgw_config、dpl_sgw_logs | sgw_gw_config、sgw_gw_logs |
| Docker 网络 | dpl_sgw_net,172.28.31.0/24 | 原项目网络 |
现场 SubSieve 的接口和界面只有一个上游,没有发现直接维护两个机场的上游列表。因此采用同机第二实例,独立配置、凭据、卷和端口。新网关限制 160MB,管理容器限制 128MB,分别限制 0.5 CPU;管理端口不开放公网。以后新增 dpl 节点复用这套网关,无需重复部署。
节点使用官方 cedar2025/Xboard-Node v1.13,Linux amd64 文件 SHA256 为 55bf71fa9d9f2048d3255ae7c0af929a41897ca7743f6ead34132a6ca4c79043。独立 systemd 服务及配置目录,不更新或重启 XrayR。网关固定镜像 ID 见 scripts/node-onboarding/gateway.compose.yml。共享宿主机的容量须在每次变更前重新核验。
## DNS、真实 IP 和证书
Namecheap 已委托至 bradley.ns.cloudflare.com、jewel.ns.cloudflare.com。导入的原有记录保留。c2 指向网关并启用代理;us01 指向节点,DNS only。两张源站证书有效期至 2027-01-09,公网订阅 HTTPS 可用。
Cloudflare Full (strict) 曾提交保存,但保存后的账户状态因网站权限拦截未复核;显式订阅 Cache Rule 尚未创建,不能据公网 HTTPS 正常写成已完成。当前实际订阅返回 CF-Cache-Status: DYNAMIC、Cache-Control: private, no-store。
恢复浏览器权限后的收尾配置已确定,尚未执行:
1. 在 deeplink-subscribe.com 的 SSL/TLS 页面读取保存后的模式,确认 Full (strict),同时核对是否有覆盖 c2 的 Configuration Rule。源站已有有效域名证书;不能只看浏览器锁标志判断回源校验模式。
2. 在 Cache Rules 新增 `dpl-c2-subscription-bypass`,Custom filter expression 为 `http.host eq "c2.deeplink-subscribe.com"`,Cache eligibility 选择 Bypass cache。c2 专用于订阅,因此整个该主机绕过缓存;其他主机不匹配。
3. 检查既有规则,将这条规则置于可能匹配 c2 的缓存资格规则之后,避免后续规则覆盖。部署后刷新页面复核名称、条件、动作及顺序,再核对订阅响应仍为 private/no-store,且没有 HIT 或 Age。
依据 Cloudflare 官方说明:[Full (strict)](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/)、[创建 Cache Rule](https://developers.cloudflare.com/cache/how-to/cache-rules/create-dashboard/)、[规则顺序](https://developers.cloudflare.com/cache/how-to/cache-rules/order/)。上述内容是待执行配置,不是完成记录。
宿主 Nginx 只信任 Cloudflare 官方网段的 CF-Connecting-IP,再向新容器发送清洗后的真实 IP。新容器仅信任本项目网桥 172.28.31.1。实际公网请求的 Cloudflare trace IP 与新网关日志已逐值比对一致,文档不保留个人 IP。
按用户追加授权,原机场两个订阅 vhost 也已加入 /etc/nginx/dpl-cloudflare-realip.conf,其余内容保留。写入前备份、nginx -t 和平滑重载通过;vhost 级信任列表替代继承的旧静态列表。原容器内的网桥信任配置保留,原订阅经 Cloudflare 的请求也已核对到访问者出口 IP。
dpl-cloudflare-ips.timer 每日宿主机时间 02:00 执行,随机延迟最多 15 分钟。脚本下载官方 ips-v4 / ips-v6,校验地址族、CIDR、数量、重复和过宽网段,完整有效才原子替换;下载/校验失败保留上次文件,Nginx 检查/重载失败回退文件。当前成功同步 22 段、定时器启用。不是实时推送;失败记录在 journal,没有主动告警,尚未执行故障注入验收。
新网关 Certbot 独立使用 /etc/dpl-letsencrypt,由 dpl-gateway-cert.timer 每日 03:00、随机延迟最多一小时续期。--no-directory-hooks 避开原机场全局钩子,专用钩子只检查/重载新网关、新管理容器和宿主 Nginx。新网关和新节点的续期 dry-run 均已通过;网关专用 deploy hook 实际执行检查/重载通过,原容器启动时间未变。ACME webroot 为 /var/lib/dpl-sgw/acme,父目录须允许 Nginx worker 遍历;admin.env 保持 600,验收目录保持 700。
节点续期钩子只匹配 /etc/dpl-node/certificate-domain 中的域名并 try-restart dpl-node,不操作 XrayR。首次签发前须审计既有 pre/post/deploy 钩子及 renewal 配置;不能认为签发新域名仅影响新服务。
### 首次签发期间的原网关重启
首次 c2 签发前未充分审计既有 Certbot 全局 deploy hook,触发它重启了一次原 subscribe-gateway,时间为 2026-10-11 08:14:19 UTC。原管理容器未重启。已告知用户,后续将新证书注册/续期迁至独立目录并禁用原目录钩子;原钩子本身未修改。
原网关重启后运行正常,原订阅路由回归通过,容器 ID 保持原值;之后的新证书钩子及 IP 同步未再次重启原容器。不能据后续回归通过声称整个任务中原网关从未重启,或证明当时所有用户均无感。
## 新节点参数单
| 参数 | 首次实例 | 后续填写规则 |
| --- | --- | --- |
| key / name | us01 / 🇺🇸 美国 US - 01 | 唯一 key;旗帜、中文国家、国家代码、两位序号 |
| server | node-us01 | 从 CoDocs 项目关系及连接资料确认 |
| listen-port | 24443 | 当场核对 TCP/UDP 和防火墙,不复用过期判断 |
| relay-host / relay-port | haiwi.lshan.eu.org / 47101 | 新增规则,不改原规则 |
| tls-domain | us01.deeplink-subscribe.com | DNS only,有效证书 |
| group / plans | 首次隔离组;套餐 1、6、7、8 | 当前真实 ID 和授权集合 |
| backup | /root/codex-backups/dpl/node-onboarding-20261011-us01 | 每节点独立时间/key 目录 |
## 重复执行步骤
1. 读取根 AGENTS、维护入口和本文。经 CoDocs 白色机中转访问服务器;本地网页使用指定访问域名。记录原服务 PID/启动时间/端口、中转规则、Docker ID/启动时间、原订阅结果;审计资源、防火墙、所有证书钩子。受保护备份本次将修改的配置和 Git 差异,不输出私密内容。
2. 非敏感脚本和模板先 Git 提交/推送,再更新服务器到明确提交,保留生产原有差异。无法直接拉取时可传输已推送提交的 Git bundle 后 fetch/fast-forward,不能用压缩包覆盖。scripts/node-onboarding 可 subtree split 为独立运维仓库;面板 .env 不送到节点。
3. 在生产应用根目录按参数单运行 stage.php,创建机器、AnyTLS 节点、隔离组和 100MB/一天的临时用户。节点虽启用显示,正式用户没有隔离组权限。相同 manifest 重跑只报告已创建;同名资源存在却缺少 manifest 时停止,不自动接管。
```sh
php scripts/node-onboarding/stage.php \
--key=us01 --name='🇺🇸 美国 US - 01' \
--relay-host=haiwi.lshan.eu.org --relay-port=47101 \
--listen-port=24443 --tls-domain=us01.deeplink-subscribe.com \
--backup=/root/codex-backups/dpl/node-onboarding-20261011-us01
```
4. 将受保护备份的 node-config.yml、node-secret.env 经白机安装到节点 /etc/dpl-node/config.yml、secret.env,均 600;运维仓库 checkout 明确 Git 版本到 /opt/dpl-node/provision。首次安装使用下面命令。脚本检查参数、配置、端口、已有后端及 XrayR 状态,校验官方二进制并安装独立 unit,不自动启动。已有 dpl-node 时不能重跑覆盖;升级须单独复核。
```sh
bash /opt/dpl-node/provision/install-node.sh \
--listen-port=24443 --tls-domain=us01.deeplink-subscribe.com
```
5. 配置 DNS only、有效证书并审计/安装仅匹配新域名的续期钩子,再启用 dpl-node。在中转后台只新增 dpl-<key>-anytls,核对保存后的入口/目标和诊断结果。本次未启用收发 Proxy Protocol,以后启用前须同时确认入口和后端支持。
6. 后续 dpl 节点复用 c2 及当前网关,不再次更换 NS。另一个机场需要不同上游时才新增独立实例;不得改已有上游、运行原项目 setup/update/down 或复用旧卷。
7. 在网关创建本次验收目录(700),以 600 保存 stage.php 生成的 QA 私密文件和实际订阅;准备官方客户端并校验官方发布摘要。首轮已校验的 Linux 1.14.3 客户端保留于 /opt/dpl-gateway/acceptance/,下述命令可复用它。拉取临时用户完整订阅到私密文件;sing-box 使用正常版本 UA(如 sing-box/1.14.3),不要使用覆盖版本识别的裸 flag=sing-box。核验名称、入口、SNI、严格 TLS、缓存头和真实 IP;先官方客户端 check,再完整配置实际联网,核对出口、DNS、上下行计费与上报。
```sh
python3 /opt/dpl-gateway/provision/verify-node.py \
--qa /var/lib/dpl-sgw/qa/qa.json \
--binary /opt/dpl-gateway/acceptance/sing-box-1.14.3-linux-amd64/sing-box \
--subscription /var/lib/dpl-sgw/qa/subscription.json \
--expected-exit 64.44.115.18
```
helper 仅替换 TUN 等入站为临时本机 SOCKS,保留订阅 DNS、分流及出站,退出时停止客户端;失败日志留在同一私密目录。这不等于手机 GUI、系统 TUN、多地区、超额或多设备并发验收。某环境到入口不通时分段诊断并换环境核验,HTTP 200 不能替代联网。
8. 上述验收通过后,在生产根目录运行 readiness.php 和 promote.php,显式指定当前套餐集合。已有正式组时额外传 --group=<ID>。只关联所选尚无组的套餐及这些套餐现有无组用户,不改价格、周期、流量或设备限制。
```sh
php scripts/node-onboarding/readiness.php \
--backup=/root/codex-backups/dpl/node-onboarding-20261011-us01
php scripts/node-onboarding/promote.php \
--backup=/root/codex-backups/dpl/node-onboarding-20261011-us01 \
--plans=1,6,7,8
```
首次隔离组改为基础节点、订阅域名设置为 c2,以后复用正式组。脚本要求节点在线且临时用户已有流量,保存 before-promotion.json,最后禁用临时用户并写 promoted.json。清理本次客户端和私密传输副本,保留服务器备份、禁用用户与审计记录。
9. 回归原机场服务/规则/订阅,实际核对正式组权限、面板节点及订阅域名保存,确认测试用户禁用且不再下发。更新本文及 STATUS,分别记录提交、发布、真实验收及未完成项。
数据库默认 sing-box 模板已迁移新 DNS/路由格式,保留原分流和选择逻辑;现代本地 DoH 使用默认 dialer,不绕到空 direct 出站。仓库原默认资源和其他机场模板不改。apply-template.php 仅接受原默认模板,或与显式 expected-current-sha256 完全匹配的旧版本,逐次备份后只更新该模板/缓存。用户定制或未知模板须先审查,不能强行覆盖。
## 回退与排障
- 单节点:停用本次节点/新增中转,停止新 dpl-node;保留 XrayR、原规则和审计数据。
- 正式关联:依据 before-promotion.json 精确恢复本次套餐/用户组及订阅域名,先确认当前值仍是本次写入值,避免覆盖后续业务。不恢复整库。
- 模板:从对应私密模板备份恢复该条内容并清理模板缓存,不替换整个设置表。
- 网关:只停新 Compose 项目、撤回新域名 vhost,检查后平滑重载。不能停止原项目、删原卷或改原上游;独立证书目录和定时器按本次备份回退。
- IP 同步:检查 dpl-cloudflare-ips.service、journal 和最后有效文件,不退化为信任所有来源。原 vhost 的追加授权变更可按专用备份独立回退。
- 浏览器保存拒绝:检查 Codex Settings → Browser → Agent permissions 的 Browse 网站规则及覆盖规则;仍拦截则重新启动应用后复核。不能用其他控制方式绕过拒绝,公网结果不能替代账户设置核验。
## 节点登记及验收边界
| 机场 | 节点 | 协议 | 落地 | 中转 | 面板 ID | 状态 |
| --- | --- | --- | --- | --- | --- | --- |
| dpl | 🇺🇸 美国 US - 01 / node-us01 | AnyTLS | 24443 | haiwi.lshan.eu.org:47101 | 1 | 已上线;基础节点组,正式套餐 1/6/7/8 |
已完成:独立服务、节点 TLS、新中转、新网关、DNS/橙云、真实 IP 比对、新旧订阅 vhost 官方 IP 自动同步、两张证书续期演练。官方 sing-box 1.14.3 的完整实际订阅(仅把入站替换为临时本机 SOCKS)经中转联网,出口 64.44.115.18、US、HTTPS TLSv1.3,严格节点证书校验;完整 DNS 和远程分流规则实际启动通过,面板已记录上下行流量。
用户随后具体授权正式开放:套餐 1/6/7/8 和其中 1 位现有无组用户已关联基础节点组,界面核对节点在线、命名和组名正确;站点设置订阅 URL 实际显示 c2。临时用户已禁用,订阅返回 403,实际下发用户集合不再包含该用户;正式用户可见该节点。价格、周期、流量和设备限制未改。本机临时客户端已停止。
核心代码发布为 3b72c3e3c182313ebdae9f81a6e83712775942a3;节点/网关独立运维仓库为 b05c3215505c6ea70042aed0b102c682406528be。面板生产已有教程及文件模式差异保留。最初本机至中转出现 EOF,节点直连 TLS 正常;网关主机环境的完整中转客户端测试通过,不能据该结果保证用户所在所有地区路径可达。截图见 codex/output/node-us01-planning/node-live.png 与 relay-created.png。
最终分段复核:本机与已测通网关的入口 DNS 均为 199.30.91.63,本机直连 64.44.115.18:24443 的严格 TLSv1.3 握手成功,但本机到中转 47101 仍为 TLS EOF。现有后台只有隧道 17517,新增表单未提供备用监听 IP;仅查看后取消,没有创建额外规则。用户确认本机开启代理,随后明确要求跳过本地连通测试,已停止这一排查。本地结果记为跳过且原因未定位,不再作为本次交付阻塞项,也不记为通过;用户网络可达性没有保证。
仍待完成:Cloudflare Full (strict) 后验及显式缓存规则;工具仍报告 dash.cloudflare.com 被保存的拒绝权限拦截,用户需解除实际规则或重启应用后再核验。本地连通按用户要求跳过;GUI/手机导入、系统 TUN、多地区、超额及多设备并发不在已执行验收范围内。
后续可直接给维护代理:“按 docs/maintenance/NODE_ONBOARDING.md 接入 dpl 的下一节点,先填参数单、复核共享资源和证书钩子,只新增,不动原机场;完整订阅实测后再开放指定套餐,更新登记与 STATUS。”本文不启动聊天结束后的自动维护。