# 105 · 覆盖网络 · 骨干层方案 - 日期:2026-09-16 | 状态:📋 **规划态 / 未实施**(设计稿;未接入任何机器) - 来源:工作区根 `覆盖网络_骨干层方案_20260916.md`(正文见 附录 A) - 层级:专项设计(承接档案 **106** §7 P0-1 的展开)|关联:档案 104 §7 落地顺序第 7 步 - 触发(用户原话):**有公网 IP 的节点是否可以设置专门的网络服务,让其他有公网 IP 的节点加入形成专门的覆盖网络,其他用户节点可以选择性加入** > **TL;DR** > ✅ **可以,而且是成熟系统里的标准模式** —— 业内叫「**超级节点 / 骨干层(supernode / backbone)**」(ZeroTier Moon · Nebula Lighthouse · Tailscale DERP · libp2p AutoRelay · 早期 Skype supernode)。 > 它解决的正是推演里最贵的那条:**中继容量要按 45–55% 的 L3 占比预留**,靠一台中心服务器扛不住 —— 而网络里本来就躺着现成的公网出口。 > 🔑 三条硬约束:**接入 / 成员 / 可见三分离**;**骨干资格只能控制面签发**;**骨干不得被默认征用**。 ## 一、目标 把「有公网 IP 的节点组成骨干层、其他节点选择性加入」设计成可落地方案。可判定「做完了没有」= 形态(多中心)· 成员上限 · 三条硬约束 · 容量数字 · 兼容性判定 · 落地 5 步 齐备。 ## 二、只读前置 | # | 事实 | 核对方式(期望输出) | |---|---|---| | 1 | 骨干 = **一种新的 host 类型**,与 T08 host/lease 模型兼容(属新增能力标签) | 读 `src/db/`(lease)与集群化设计 §1.3 | | 2 | 会合 / 中继**属数据面,架构本来允许多实例**;**归属/租约/资格必须单点控制面** | 集群化设计 §1.3 | | 3 | 现有中继实现 = **挂在 Manager 上的 SSH 反向隧道(单中心)** ⇒ 落地第一步就是拆组件 | `sed -n '147,155p' src/worker/tunnel.ts` | | 4 | 打包与分发可复用桌面客户端独立仓库的打包/更新链 | 见 `dsh桌面客户端_开发方案_20260916.md` §3.4/§6 | | 5 | 骨干全靠**用户态 UDP/TCP**,**不需要特权** | 本档 §1 表「骨干承担」行 | ## 三、范围 - **改什么**:⏳ 未开跑。方案面 = ① 拆会合/中继为独立可部署组件 ② 控制面签发骨干资格 + 下发**签名目录** ③ 骨干互认心跳(≤10 成员全互联)④ 接入选路(主/备,秒级迁移)⑤ 接入与可见解耦 ⑥ 可选「贡献带宽给全网」开关。 - **不动什么**:⛔ 权威状态(归属 / 租约 / 资格)**不得由骨干自行批准**|⛔ 本轮不动服务器、不改代码。 - **红线约束**:R5(骨干若默认替全网转发 = **扩大权限面 + 占用他人资源**,命中 R5 与边界外 ⇒ 必须显式开关)。 ## 四、决策点 **已定** 1. **形态 = 多中心骨干**(取代单中心星型):骨干成员上限 **≤10–20**(10 个 = 45 条;20 个 = 190 条;50 个 = 1,225 条)。 2. **普通节点每台只连 1–2 个骨干**(主用 + 备用)⇒ 100 台 = 100–200 条常连,完全可控。 3. **资格只能由控制面签发**(不得由骨干节点自行批准,否则出现第二个权威源、骨干沦为公网跳板)。 **待拍板(唯一一项,真取舍 —— 与档案 104 §四 同一项)** **骨干节点的服务范围**: - **A · 只服务自己名下的设备(自用骨干)** 优点:无合规与计费问题;不占用他人资源;**权限面不变(不命中 R5)**;实现最简单,节点只认自己的主人。 缺点:骨干数量受限于「有几个用户有公网 IP 的机器」;跨用户无法互相兜底,冗余度低。 - **B · 服务全网(共享骨干)** 优点:骨干多、冗余好、可用性高;单个骨干挂了影响小;对 L3 那 40–55 台的中继容量最容易满足。 缺点:**他人的流量跑在你的机器上**(资源与计费要立规矩);骨干会看到流量元数据(谁连谁、流量大小);节点被攻破的影响面变大。 **倾向 A→B 渐进**:先把骨干做成「自用骨干」跑通(零合规风险、可立刻验证),把「是否贡献带宽给全网」做成**显式开关**,等 A 稳了再逐个放开。 ## 五、步骤(§8 落地顺序;每步自带一次验证) 1. **把会合 / 中继从 Manager 里拆出来**,做成可独立部署的组件 → 验证:Manager 重启不影响骨干侧已有转发。 2. **控制面签发骨干资格 + 下发签名目录**(骨干之间只校验,不自行批准)→ 验证:未签发的公网 IP 无法成为骨干。 3. **骨干互认与心跳**(≤10 个成员,全互联)→ 验证:45 条常连心跳 ≈ 2.3 req/s(可忽略)。 4. **接入选路**(节点就近选主/备骨干,支持秒级迁移)→ 验证:掐掉主骨干,节点秒级迁到备用。 5. **接入与可见解耦**(默认只见自己名下设备)→ 验证:借骨干转发时**不暴露对端清单**。 6. 可选:开放「贡献带宽给全网」开关(= §四 的 B 档)。 ## 六、验收 | # | 口径 | 期望 | |---|---|---| | A | 骨干规模与常连数 | 10 个骨干 ⇒ 骨干内 **45** 条常连;每骨干接入 10–20 个节点 | | B | 中继容量摊开 | 稳态 20–27 Mbps 摊到**多个**骨干,而非一台 | | C | 单点故障收敛 | 骨干挂 1 个 ⇒ 受影响 = 接入它的 10–20 台,**秒级迁到备用**(不是全网掉线) | | D | 目录可用性 | 骨干目录不可达时**用本地缓存的签名目录**继续选路(目录不能是单点) | | E | 故障影响面 | 骨干被攻破 ⇒ 影响面 = 接入它的那批节点(**不是全网**) | | F | 未验证项透明 | §九 四条已列全(网络类型占比、家宽上行是否够、全互联收敛开销、SSH 隧道改造工作量) | ## 七、回滚 - **本档自身**:零改动 ⇒ 无回滚需要。 - **执行期**:5 步各自独立可回滚 —— 拆组件(回退到 Manager 内置隧道)|签发资格(停发即回到无骨干态)|互认心跳(关服务)|选路(回落到单骨干)|解耦(关开关)。 - ⛔ **不可回滚项**:控制面签发资格这一条是**红线**(一旦下放给骨干自行批准即产生第二权威源)—— 不是开关。 ## 八、回报格式 执行会话回填:① 每步验证命令 + 实际输出 ② 骨干清单与上限实际取值 ③ 服务范围决策落地形态(A / A→B / B) ④ 红线遵守声明(R5 未默认征用他人带宽 / 资格由控制面签发) ⑤ commit ⑥ 未完成项与卡点。 ## 九、未验证项(勿当结论) 各网络类型实际占比(决定骨干数量需求,**推演设定**)|骨干节点上行带宽是否够(**家宽上行常远小于下行,未实测**)|骨干全互联在 ≤10 成员时的实际收敛开销(量级推算 2.3 req/s)|现有 SSH 隧道改造为独立组件的具体工作量(**待评估,未读该模块全量代码**)。 --- ## 附录 A · 原始规划正文(逐字保留 · 2026-09-16) > 以下为工作区根 `覆盖网络_骨干层方案_20260916.md` 的**原文全文**,仅删除其一级标题(避免与档案标题重复), > 其余**一字未改**;本档的可判定部分以上方 8 段为准。 > 日期:2026-09-16 | 性质:**设计稿**(承接 `覆盖网络_百台规模推演_20260916.md` **P0-1** 的展开) > 用户提出:**有公网 IP 的节点是否可以设置专门的网络服务,让其他有公网 IP 的节点加入形成专门的覆盖网络,其他用户节点可以选择性加入** > 🟢 **范围**:**只考虑技术实现,跨境数据合规由使用者自行考虑**(同 `覆盖网络_全球架构复盘_20260916.md` §0 范围声明) --- ## 0. 判定 ✅ **可以,而且这是成熟系统里的标准模式** —— 业内叫「**超级节点 / 骨干层(supernode / backbone)**」,不是新造东西。 | 先例 | 骨干层是什么 | |---|---| | ZeroTier | Planet(官方根)+ **Moon(自建公网节点)** | | Nebula | **Lighthouse**(有公网 IP 的会合点,可多台冗余) | | Tailscale | **DERP 中继** + exit node / subnet router("提供服务的节点") | | libp2p | **relay v2 + AutoRelay**(有公网 IP 的节点自动成为中继候选) | | 早期 Skype | **supernode**(有公网 IP 的节点自动升格) | | EasyTier / 自建方案 | 指定"公网节点"作为中继与路由 | **它解决的正是推演 v2 里最贵的那条**:中继容量要按 45%–55% 的 L3 占比预留 —— 靠一台中心服务器扛不住,而网络里本来就躺着现成的公网出口。 --- ## 1. 形态:**多中心骨干**(取代单中心星型) ``` ┌──────── 骨干层(有公网 IP,互相可直接连)────────┐ │ S1 ── S2 ── S3 ── … ── Sn (全互联或有界互联) │ └───┬──────┬──────┬───────────────┬───────────────┘ │ │ │ │ ← 选择性加入 ┌─────┴─┐ ┌──┴───┐ ┌┴────┐ ┌────┴───┐ │家宽节点│ │移动网 │ │企业网│ │ VPN 节点│ ← L2/L3 层节点 └───────┘ └──────┘ └─────┘ └────────┘ ``` | 项 | 取值 | 理由 | |---|---|---| | 骨干成员 | **有公网 IP 的节点**(服务器 / 专属 IP) | 互相可直接连,无需打洞 | | 骨干互联 | **全互联,但成员数设上限** | 10 个 = 45 条;20 个 = 190 条;50 个 = 1,225 条 ⇒ **建议 ≤10–20** | | 普通节点接入 | 每台只连 **1–2 个骨干**(主用 + 备用) | 100 台 ⇒ 100–200 条常连,完全可控 | | 骨干承担 | 会合(rendezvous)· 中继(relay)· 可选 STUN-like 探测 | 都是用户态 UDP/TCP,**不需要特权** | --- ## 2. 一个骨干节点要跑什么(可以打成一个独立组件) | 服务 | 作用 | 流量特征 | |---|---|---| | **会合** | 把两个节点的候选地址互相告诉对方 | 极小 | | **中继** | 打洞失败时转发密文 | **大**(按 L3 占比算) | | **NAT 探测** | 帮节点判断自己的映射类型 | 极小 | | **目录镜像**(可选) | 分发"有哪些骨干可用"的**签名目录** | 小 | ⇒ 这四样打包成一个「节点服务」,**正好可以放进桌面客户端那个独立仓库**(复用打包与更新链),不需要碰平台主进程。 --- ## 3. 三条必须钉住的设计约束 ### 3.1 「选择性加入」必须拆成三个独立概念(否则一定出事) | 层 | 含义 | 归属 | |---|---|---| | **接入**(connectivity) | 我能通过谁到达别人 | 节点自选(就近 / 按容量) | | **成员**(membership) | 我在不在网里、谁批准 | **控制面签发 + 可吊销** | | **可见**(visibility) | 我能看到/访问谁 | **ACL,默认最小** | ⚠️ **最危险的默认**是"加入骨干 ⇒ 能看见骨干上所有人"。那会变成一张巨型扁平网,与项目"**权限只准收窄**"直接冲突。 ⇒ **接入与可见必须解耦**:可以借骨干做**转发通道**,而不暴露对端清单。 ### 3.2 骨干资格:**只能由控制面签发**(不得由骨干节点自行批准) - 若骨干节点能自行批准新成员 ⇒ 出现**第二个权威源**(违反单一来源),且**任何人开个公网 IP 就能进骨干** ⇒ 骨干沦为公网跳板。 - 正确形状:**控制面签发骨干成员资格(可吊销)+ 骨干之间只做"校验签名"**,不自行决策。 - 与平台既有分层判据完全一致:**会合/中继可以多实例(数据面),权威状态必须单点**。 ### 3.3 骨干节点**不能**被默认征用去转发别人的流量 - 骨干节点的带宽可能属于**贡献者本人**。若默认"为全网转发" ⇒ **扩大权限面 + 占用他人资源**(命中 R5 与边界外)。 - ⇒ 必须显式:**服务范围**(只服务自己名下设备 / 服务全网)+ **带宽上限** + **随时退出**。 - 这一条需要用户定,见 §7。 --- ## 4. 容量与数字(沿用推演 v2 的分层口径) | 项 | 取值 | |---|---| | 100 台构成 | L1 有公网 IP **10** | L2 可打洞 **30** | **L3 只能中继 40–55** | | 骨干规模 | 10 个 ⇒ 骨干内 **45** 条常连 | | 每骨干接入 | **10–20** 个节点(100 / 10 上限) | | 骨干心跳 | 45 条 × 1/20 s ≈ **2.3 req/s** ⇒ 可忽略 | | 中继稳态 | 20–27 Mbps 总量,**摊到多个骨干**而非一台 | | 骨干挂 1 个 | 受影响 = 接入它的那 10–20 台 ⇒ **秒级迁到备用骨干**(不是全网掉线) | ⇒ 相对单中心,**多中心骨干把"中继带宽"与"单点故障"同时摊开了** —— 这是它最大的收益。 --- ## 5. 故障与运维面 | 场景 | 期望行为 | |---|---| | 骨干 S2 挂 | 接入它的节点秒级迁到备用骨干;正在进行的连接会断一下 | | 骨干目录不可达 | **用本地缓存的签名目录**继续选路(目录不能是单点) | | 骨干被攻破 | 影响面 = 接入它的那批节点(**不是全网**)⇒ 优于单中心 | | 骨干换 IP / 身份轮换 | 由控制面更新目录,节点热切换 | | 节点从骨干 A 迁到 B | 新旧路径短暂并存,避免"先断后连"的可见中断 | --- ## 6. 与现平台架构的兼容性(**这是能不能落地的前提**) | 项 | 判定 | |---|---| | 骨干 = 一种新的 **host 类型**(有公网 IP、可做中继) | ✅ 与 T08 的 host / lease 模型兼容,属**新增能力标签** | | 会合 / 中继多实例 | ✅ 属数据面,**架构本来就允许多实例** | | 归属 / 租约 / 骨干资格 | ⛔ **必须单点控制面** —— 客户端与骨干一律不得持有权威状态 | | 现有中继实现 | ⚠️ 现在是**挂在 Manager 上的 SSH 反向隧道**(单中心)⇒ 落地第一步就是**把它拆成可独立部署的组件** | | 打包与分发 | ✅ 复用桌面客户端独立仓库的打包/更新链 | --- ## 7. 需用户拍板的一项(真取舍) **骨干节点的服务范围**:是只服务自己名下的设备,还是替全网(含其他用户)转发流量。 **A · 只服务自己名下的设备(自用骨干)** 优点:无合规与计费问题;不占用他人资源;权限面不变(不命中 R5);实现最简单,节点只认自己的主人。 缺点:骨干数量受限于"有几个用户有公网 IP 的机器";跨用户无法互相兜底,冗余度低。 **B · 服务全网(共享骨干)** 优点:骨干多、冗余好、可用性高;单个骨干挂了影响小;对 L3 那 40–55 台的中继容量最容易满足。 缺点:**他人的流量跑在你的机器上**(资源与计费要立规矩);骨干会看到流量元数据(谁连谁、流量大小);节点被攻破的影响面变大。 **我倾向 A→B 渐进**:先把骨干做成"自用骨干"跑通(零合规风险、可立刻验证),把"是否贡献带宽给全网"做成**显式开关**,等 A 稳了再逐个放开。 --- ## 8. 落地顺序(每步可单独回滚) 1. **把会合 / 中继从 Manager 里拆出来**,做成可独立部署的组件(当前是绑定在 Manager 上的 SSH 隧道)。 2. **控制面签发骨干资格 + 下发签名目录**(骨干之间只校验,不自行批准)。 3. **骨干互认与心跳**(≤10 个成员,全互联)。 4. **接入选路**(节点就近选主/备骨干,支持秒级迁移)。 5. **接入与可见解耦**(默认只见自己名下设备)。 6. 可选:开放"贡献带宽给全网"开关(= §7 的 B 档)。 --- ## 9. 未验证项 | # | 项 | 状态 | |---|---|---| | 1 | 各网络类型实际占比(决定骨干数量需求) | ⚠️ 推演设定 | | 2 | 骨干节点的上行带宽是否够(家宽上行常远小于下行) | ⚠️ 未实测 | | 3 | 骨干全互联在 ≤10 个成员时的实际收敛开销 | 📋 量级推算(2.3 req/s) | | 4 | 现有 SSH 隧道改造为独立组件的具体工作量 | 📋 待评估(未读该模块全量代码) |