chore(工作区): 纳入版本控制基线(回收 411 MB 过程产物)
回收 411 MB(470 M → 58.8 M),全部经回收站,可恢复: - 待清理/(146.2 M,含 relay 分片 128 M 与 42 项过程目录) - tmp/(32.4 M,按接续棒命名的过程临时区) - .workbuddy/tmp/(39.5 M) - 4 份 workbuddy.db 冗余副本(101 M,09-23 事故的坏副本 / 抢救产物) - tmp/im16/gw/centrifugo 二进制(63.9 M,可重下)+ 缓存残留 入库范围:常驻规则(CODEBUDDY.md / README.md / state.py)、在途接续入口与 接续包、docs/、交付物/、交接单/、归档/、scripts/、.codebuddy/、 .workbuddy/memory/;共 398 件,其中 >60 KB 的 26 件全为文档。 排除(.gitignore):tmp/、待清理/、运行态日志与缓存、*.db 与 DB 备份整目录、 打包二进制(*.tar.gz / *.tgz)、记忆修复前备份。
This commit is contained in:
commit
ce8e6ceed9
396 files changed
+66045
No files matched your search
@@ -0,0 +1,113 @@
|
||||
# 覆盖网络 · 设备登录接入 —— 决策与改造方案(2026-09-20)
|
||||
|
||||
> **一句话**:中继承载走 **C(直连打洞优先、中继兜底)+ A(relay 集群横扩)**,**B(分层中继)后续再考虑**;凭证分发改成"**设备带用户登录态换 per-device grant**",人工 invite 通道只留给服务器节点。
|
||||
> **执行载体**:交接单 `D:\github\dsh_shenxian\dsh-server-docs\交接单\覆盖网络-序46-设备登录接入网络.md`(本文件只做决策与背景沉淀,⛔ 不含逐步操作)。
|
||||
|
||||
---
|
||||
|
||||
## §0 用户口径(原话,⛔ 不改写)
|
||||
|
||||
- 「想知道50w个客户端要接入覆盖网络,怎么给这些设备一个个发凭证,那登录注册不用留着干啥」
|
||||
- 「c + a 后续再考虑b 沉淀文档,改造功能支持设备登录接入网络,然后再对接文档中写明接入方式」
|
||||
|
||||
⇒ 三件事:① 决策沉淀 ② 功能改造(设备登录接入) ③ 对接文档写明接入方式。
|
||||
|
||||
---
|
||||
|
||||
## §1 结论(先给判定)
|
||||
|
||||
1. **凭证分发不是瓶颈**:一次 Ed25519 签名是微秒级,50 万张凭证= 50 万次自动签发,零人工。
|
||||
2. **人工 invite 不是分发通道**:它服务"没有账号的服务器节点"(几十台)。设备接入的授权来源是**用户登录态**。
|
||||
3. **真正要改造的是三处**:① relay 的 `DIAL` 白名单是**逐 hostId 名单**(不可扩展)② 网注册表是**单 JSON 全量读写**(不可扩展)③ 缺"用户态签发端点"(现在只有本机 CLI)。
|
||||
4. **承载才是花钱那一项**:50 万条长连接必须 relay 集群横扩(路线 A);打洞成功的那部分不过中继(路线 C),成本曲线最缓。
|
||||
|
||||
---
|
||||
|
||||
## §2 现状取证(2026-09-20 只读实测,⛔ 别凭记忆复用)
|
||||
|
||||
| 事实 | 证据 |
|
||||
|---|---|
|
||||
| relay 强制身份校验 | 47 `dshs-relay` env `DSHS_OVERLAY_REQUIRE_IDENTITY=1`;`loadIdentityForServer()` 配不全即**起动抛错** |
|
||||
| 两道独立证明 | `server.ts`:① `grant + grantSig` 由受信签名者签 ② `nodeSig` 证明握有节点私钥(光有证书=可转发,所以必须第②条)|
|
||||
| 受信签名者来源 | **不是** env `DSHS_OVERLAY_SIGNER_PUBKEYS`(47 上没有该变量)⇒ 实际 = `/etc/dshs/overlay-signers.json`(SignerSet,由 `DSHS_OVERLAY_ROOT_PUBKEYS` 验签);签名者公钥 hex = `bad464dfd53048efe7b8531029b3030eda49bc12930703d3a2a8f60e3a7daddf` |
|
||||
| `DIAL` 白名单 | `dialers` 按网分桶、**构造时定型、运行期不可改**;`DIAL` 默认拒绝;落点 = 单个 drop-in 的 `Environment=DSHS_RELAY_DIALERS=网/host,…`(`registry.ts#deriveDropIn`)|
|
||||
| 网注册表 | `/var/lib/dshs/overlay/nodes.json` = **单 JSON 全量读写**(`loadRegistry/saveRegistry`);47 上内容为**空** `nodes:{}` |
|
||||
| invite 通道**不产 grant** | `grep grant scripts/overlay-node-admit.cjs` = 空 ⇒ 走 invite/join 的节点只进白名单,在 `REQUIRE_IDENTITY=1` 下仍会被 `verifyPeerGrant` 拒 |
|
||||
| 在线接收端点**未实现** | `grep "overlay/join" src/` = 空;`GET /dshs-overlay/bootstrap` 是**地址目录**(可轮换种子),不是签发入口;overlay 管理端点全 `requireAdmin` |
|
||||
| 网名三形态 | `ops`(运维网)|`u:<租户>`(租户网)|具名网;节点逻辑名 = `<network>/<hostId>` |
|
||||
| 既有规模推演 | `覆盖网络_千台全场景推演_20260916.md`(**千台**量级)⇒ 50 万台超出两个数量级,须重做推演 |
|
||||
|
||||
---
|
||||
|
||||
## §3 目标形态:设备登录接入
|
||||
|
||||
```
|
||||
设备首启 → 本机生成密钥对(私钥 0600,永不出机)
|
||||
→ 带平台登录态调 POST /api/overlay/device-grant
|
||||
→ 平台校验:会话有效 ∧ 用户已开通客户端接入 ∧ 设备数未超配额 ∧ 公钥未在吊销清单
|
||||
→ 在线签名者当场签 NodeGrant{version,network,hostId,nodeKey,issuedAt,expiresAt}
|
||||
→ 设备持 grant + nodeSig 拨入 relay → relay 验签 + 查吊销 → 准入
|
||||
```
|
||||
|
||||
- **登录注册的作用**= 这条链的鉴权与授权来源(这台设备属于谁、进哪张网、配额多少)。
|
||||
- **一设备一 grant**,绑定 `hostId + nodeKey`(搬走无效);**可过期**(`expiresAt`,空串=不过期,仅运维常驻机器用)。
|
||||
- **短租约+拒绝续签**即等效吊销 ⇒ 吊销清单只装**紧急封禁**,不必承载 50 万条。
|
||||
|
||||
---
|
||||
|
||||
## §4 改造项 S0–S4(每项都可独立开关、可回滚)
|
||||
|
||||
### S0 · 用户态签发端点(新增)
|
||||
- 落点建议:`src/web/routes/overlay-device.ts`,路由 `POST /api/overlay/device-grant`。
|
||||
- 鉴权:**用户会话**(⛔ 不用 `requireAdmin`);入参 `{devicePubKey(64hex), deviceName}`;出参 `{network, hostId, grant, grantSig, expiresAt}`。
|
||||
- 签名:**复用 `identity.ts` 里 keyring CLI 用的那个签发函数**(⛔ 不新造签名实现);私钥仍是 47 的 `/etc/dshs/overlay-signer-key.pem`(0600)。
|
||||
- `hostId` 生成:`d-<userId>-<pubkey 前 8 位>`(满足 `isHostId`:≤63、小写字母数字 `_.-`、⛔ 不用中文/大写)。
|
||||
- 有效期:默认 24 h,键 `DESKTOP_GRANT_TTL_HOURS` 进 `config/platform.env`(⛔ 不硬编码进代码)。
|
||||
|
||||
### S1 · 客户端侧接入(属桌面线 lane)
|
||||
- grant 落 `0600`;拨入时带 `grant/grantSig/nodeKey/nodeSig` —— **现有 wire 已支持这四个字段**,协议零改动。
|
||||
- 每次启动用登录态换新 grant(=自动续期),换不到即视为被停用。
|
||||
|
||||
### S2 · relay 准入改造(**最关键**)
|
||||
- 现状矛盾:逐设备 `DIAL` 白名单与 50 万设备**结构性不兼容**。
|
||||
- 目标:设备网(`u:<tenant>`)改为「**网级放行 + 逐设备 grant 授权**」。实现二选一(执行时定):① dialers 支持网级通配(`u:5/*`)② 新增显式开关 `DSHS_RELAY_TENANT_NET_OPEN=1`。
|
||||
- 🔴 纪律:**⛔ 不把 `dialers` 改成"运行期可变"**("构造时定型"是有意的安全判据);放行粒度一律用**显式开关**表达,绝不引入隐式放行。
|
||||
|
||||
### S3 · 台账与吊销
|
||||
- 设备**不进** `nodes.json`(避免 50 万条全量 JSON);设备台账进平台 **PG** 新表 `overlay_devices(user_id, device_id, host_id, node_key, created_at, revoked_at, last_grant_at)`。
|
||||
- 吊销:优先**停发**(租约到期自然失效);紧急封禁才写 revocations 清单(`overlay-keyring.cjs sign-revocations`)。
|
||||
|
||||
### S4 · 承载:路线 C + A
|
||||
- **A**:relay 集群横扩 —— 复用既有地址目录机制(`directory.json` + `DSHS_OVERLAY_ADDR_OVERRIDES` + 无鉴权 `bootstrap` 端点做种子下发),客户端按地域/哈希选点;relay 侧仍是"每会话声明网名",一台可承载多网。
|
||||
- **C**:打洞优先、中继兜底 —— ⚠️ 前置是 **D8 云安全组放通 UDP `21100/21115`(对端 `/32`,⛔ 零个 `0.0.0.0/0`)**,未落地前打洞成功率无法测。
|
||||
- **B 分层中继**:本轮**不做**,保留为后续选项(触发条件:S4 压测显示单层集群成本/延迟不可接受)。
|
||||
|
||||
---
|
||||
|
||||
## §5 容量(**量级估算,未实测**)
|
||||
|
||||
| 项 | 量级 | 依据 |
|
||||
|---|---|---|
|
||||
| 50 万次签发 | 对平台可忽略(每次签名微秒级) | Ed25519 签名成本 |
|
||||
| 50 万条 relay 长连接 | 每连接 TLS + 用户态缓冲 **20–60 KB** ⇒ 单机 10–30 GB | **待压测**,⛔ 不作为决策依据直接引用 |
|
||||
| 单机连接数上限 | 须实测后定 | 现有观测面 `scripts/overlay-probe.cjs` 可扩展为压测 |
|
||||
|
||||
⇒ 结论:**先小规模实测"每连接成本 + 打洞成功率",再定集群规模**(否则 A 的机器数只能靠猜)。
|
||||
|
||||
---
|
||||
|
||||
## §6 风险与未决
|
||||
|
||||
1. 🔴 **relay 集群的寻址一致性**:多 relay 下"同一对节点被分到不同 relay"时的互连路径,须在 S4 明确(现网只有 2 台自研 relay,且只绑回环 20080)。
|
||||
2. ⚠️ **租户网尚未接线**:现网 relay 只有 `ops` 一张网的 dialers 桶;S2 落地前先要把 `u:<tenant>` 网端到端跑通一次。
|
||||
3. ⚠️ **grant 私钥单点**:所有设备凭证都由 47 上同一把签名者私钥签 —— 泄漏即全网可伪造。离线根可撤换签名者,但**轮换演练未做**(`overlay-keyring.cjs recover-root` 有演练能力)。
|
||||
4. ⚠️ **52 万次/天的续签请求**(24 h 租约 × 50 万设备)会打到平台 API:须做批量/合并续签或延长租约(这是 S0 的容量项,与 relay 承载无关)。
|
||||
|
||||
---
|
||||
|
||||
## §7 关联文档
|
||||
|
||||
- 交接单(执行载体):`dsh-server-docs/交接单/覆盖网络-序46-设备登录接入网络.md`
|
||||
- 对接(桌面线):`E:\ProgramData\AI技能\dsh-ai1net-desktop\docs\对接单_桌面端接入覆盖网络_给平台会话_20260920.md`
|
||||
- 规模推演(千台量级):`覆盖网络_千台全场景推演_20260916.md`、`覆盖网络_百台规模推演_20260916.md`
|
||||
- 路径/参数:`参数表_覆盖网络_20260917.md`;线入口 = 工作区根 `接续入口_覆盖网络线_20260916.md`
|
||||
Reference in new issue
Block a user