跳转至

Type 0 节点互联协议

历史兼容文档:本页只适用于 edge 分支保留的无数据库边缘运行时。dev 不启动 Type 0/TLS 节点控制面,也不解析边缘节点配置;当前中心到中心互联请阅读多中心群组互联设计。

普通设备和第三方客户端只应使用公开的 DraARLv1 Type 1-5;Type 0 只允许已认证的 edge 分支节点会话使用。edge 分支由独立的边缘配置和中心节点服务管理,不能把本页字段加入 dev 的中心配置。

1. 拓扑与端口

  • dev 分支的 draarl 二进制只运行中心模式;需要启动无数据库边缘进程时,使用 edge 分支。
  • 中心负责 HTTP、MySQL、Redis、完整路由和权限;边缘负责普通设备接入、本地转发和节点互联。
  • 边缘节点控制面使用其分支内的 TLS 配置;该控制面不属于 dev 的中心互联端口。
  • edge 分支的 Type 0 数据面与其普通设备流量共用边缘 UDP socket;中心到中心音频则使用 dev 的共享主 UDP 端口。
  • GET /api/access-points 在 dev 当前只返回配置的主中心入口。

本页后续章节描述的路由投影、节点心跳、设备下发和 Type 0 信封,均为 edge 分支兼容协议。

2. 数据路径

设备 -> 来源边缘 -> 本地 fan-out
                  -> 一份 RelayUpstream -> 中心
                                          -> 中心本地 fan-out
                                          -> 每个目标边缘一份 RelayDownstream
                                                                -> 本地 fan-out

中心按 SessionID + SessionEpoch 校验来源所有权,并从权威路由重新确定通信域和收发权限。中心不会把 Downstream 发回来源边缘;目标边缘也不会再次上传 Downstream。

Type 4 文本直接转发。Type 5 语音必须先通过 TLS 控制面的 SpeakerLease 取得中心话权,同一通信域同时只允许一个有效说话人。

边缘来源的 Type 4/5 只有在中心完成节点会话、设备所有权、路由权限、inner packet 身份和话权校验后才写入通信记录。该上行验收点是唯一记录入口;来源边缘本地 fan-out、中心本地投递和 RelayDownstream 都不重复记录。中心直连设备仍使用普通 UDP/WS 入口原有的记录流程。

3. Type 0 UDP 信封

UDP 信封最大 1400 字节。整数均使用网络字节序。

偏移 长度 字段
0 4 DraA
4 2 完整包长
6 32 SourceNodeID,零填充
48 1 Type,固定为 0
86 4 NOD0
90 1 节点协议版本
91 1 子类型
92 2 Flags
94 8 ClusterEpoch
102 8 ProjectionVersion
110 8 NodeSessionID
118 8 MessageID
126 8 SentAtMillis
134 1 HopCount
135 4 KeyEpoch
139 4 Payload 长度
143 可变 Payload
末尾 32 HMAC-SHA256

HMAC 覆盖信封头和 Payload。会话密钥、NodeSessionID 和 KeyEpoch 由已认证 TLS 控制连接建立;普通设备字段不参与节点身份判断。

节点在 TLS 握手中同时提交支持的最小/最大协议版本、功能位和必需功能位。中心 选择双方共同支持的最高版本,并只启用功能位交集;版本区间不相交,或任一方的 必需功能不在交集中时,凭据校验前即拒绝连接。当前协议范围为 1..1,功能位为:

位 能力
0 路由快照、增量与 ACK
1 Type 0 UDP Relay
2 边缘设备短期会话
3 Type 3 配置上下发
4 跨节点 Speaker Lease
5 节点运行指标
6 在线节点凭据轮换与持久化确认
7 中心重启后的边缘设备会话重新确认
8 幽灵设备实例身份、多 Session 路由、多 RX domain 与来源频道
9 幽灵 Session 短期恢复票据与续租轮换

前 3 位是当前运行所必需的能力。功能协商结果绑定到本次随机 NodeSessionID,断线重连后必须重新协商。

4. 子类型

值 名称 通道 方向
0x01 NodeEnroll TLS 边缘与中心
0x03 NodeAuth TLS 边缘与中心
0x05 NodeHeartbeat TLS 双向状态与指标
0x06 NodeDataBind TLS 挑战、UDP 证明 双向
0x07 NodeCredential TLS 中心下发轮换凭据、边缘持久化后确认
0x10 RouteSnapshotBegin TLS 中心到边缘
0x11 RouteSnapshotChunk TLS 中心到边缘
0x12 RouteSnapshotCommit TLS 中心到边缘
0x13 RouteDelta TLS 中心到边缘
0x14 RouteAck TLS 边缘到中心
0x15 RouteResyncRequest TLS 边缘到中心
0x20 DeviceAuth TLS 双向
0x21 DeviceSessionRenew TLS 双向
0x22 DeviceSessionReport TLS 边缘到中心
0x23 DeviceSessionRevoke TLS 中心到边缘
0x24 DeviceConfig TLS 双向 Type 3 配置
0x25 DeviceSessionConfirm TLS 边缘到中心批量确认,中心返回新短期授权
0x28 SpeakerLease TLS 双向 Type 5 话权
0x30 RelayUpstream UDP 边缘到中心
0x31 RelayDownstream UDP 中心到边缘

控制面使用 4 字节长度前缀的 JSON 帧承载握手消息和经过 HMAC 的 Type 0 控制信封,单个 Type 0 控制信封最大 65535 字节。路由快照最多 64 MiB,按 32 KiB 原始块分片。接收方要求分块数与声明总长度一致,每块长度必须精确匹配所在位置,内容冲突的重复块会被拒绝;全部分块通过总长度和 SHA-256 校验后才原子提交。

Flags 的 0x0010 位表示关键扩展。接收方遇到未知的非关键子类型时只丢弃该帧; 遇到未知关键子类型时必须返回通用协议错误并关闭节点会话。错误响应不回显原始 Payload、凭据或密钥。

5. 路由版本与帧龄

  • ClusterEpoch 在中心世代变化后失效旧状态。
  • 每个边缘拥有独立、连续的 ProjectionVersion,无关节点变化不会制造版本空洞。
  • Downstream 携带目标边缘所需版本;边缘落后时最多等待 1024 帧和 200 ms,追上版本后释放,否则丢弃。
  • MessageID 在节点会话内经过固定 4096 位重放窗口检查。

中心重启会生成新的 ClusterEpoch、节点控制会话和设备短期会话。边缘在 node_ready 前按每批最多 128 个设备发送 DeviceSessionConfirm,携带旧设备 会话、设备/所有者/SSID 和旧控制会话证明。标准实体设备必须与数据库中的入口 NodeID、旧控制会话和设备身份一致。幽灵设备必须额外提交中心签发的短期 HMAC 恢复票据;中心验证票据绑定的 NodeID、旧控制会话、幽灵 Session UUID、tag、 客户端实例、Owner、SSID、DevModel 和有效期,再重新查询当前用户状态与频道 权限。任一种证明失败都不得签发新授权。边缘先 原子替换本地 session ID,再应用新 epoch 的最终全量投影;确认期间收到的增量 或重同步快照只能缓存和 ACK,不能用新 ID 投影裁剪仍使用旧 ID 的本地会话, 也不能提前解除 fail closed。未协商能力、证明不匹配或超过恢复窗口的会话必须 删除并回到普通设备认证流程。

时间限制分为两层:

  1. UDP 入口使用 SentAtMillis 做 ±2 s 的粗粒度会话新鲜度检查,用于拒绝明显陈旧或未来的包。节点应启用系统时间同步,但不要求服务器时钟精确到实时帧队列的毫秒级。
  2. 包到达边缘后记录本机单调时间。200 ms 只限制本地投影等待和队列积压,不把国内外公网 RTT 或两台服务器的墙上时钟偏差算作本地排队。

因此 150 ms 等正常跨地域网络延迟不会被 200 ms 本地队列时限直接拒绝。若需要观测跨地域延迟,应在 TLS 控制面增加 RTT/时钟偏差指标,而不是把跨主机墙上时钟作为实时转发的硬条件。

6. 幽灵设备多 Session 扩展

功能位 8(NodeFeatureGhostMultiSession)和功能位 9(NodeFeatureGhostRecoveryTicket)都是幽灵 Session 的必需能力,不属于前三个实体设备基础位。新中心可以与旧边缘连接,但缺少任一能力的边缘只能继续承载标准实体设备;幽灵认证明确返回 node_ghost_multi_session_unsupported,不得静默降级身份或进入无票据恢复路径。

6.1 身份与路由字段

标准实体设备继续使用原身份编码。幽灵 DeviceGrant 和 DeviceRoute 额外携带:

字段 用途
ghost_session_id HTTP/客户端层临时 Session 的不可预测 ID
client_instance_id 同账号同平台下的稳定安装实例 UUID
session_tag UDP 热路径短标识
ghost_protocol_version 幽灵认证 payload 版本
rx_group_ids 直接接收订阅,供状态和路由更新使用
rx_domain_ids 由中心拓扑解析出的接收通信域集合
source_group_v1 目标端能否解释 DraARLv1 Reserved 来源频道
recovery_ticket 仅在 TLS 控制面传递的短期 HMAC 恢复证明;不进入客户端 UDP 包或公开 API

中心在线身份对现代幽灵使用 owner_id + ssid + client_instance_id,不会因同账号第二个手机上线而迁移第一个。节点转发和撤销使用中心签发的全局 SessionID + SessionEpoch;ghost_session_id 用于把 HTTP routing 更新精确映射到该在线入口。

group_id/domain_id 是唯一发送路由。下行目标按 rx_domain_ids 建立投影;同一 Session 因多个订阅或互联路径命中时只投递一次。来源排除使用精确 Session ID,同用户名、同 SSID 的其他客户端实例仍正常接收。disable_send 和 disable_recv 在更新多接收路由时必须保留。

6.2 Relay 与来源频道

中心只接受当前边缘控制会话拥有的 SessionID + SessionEpoch 上行,并从权威 Route 重写 DomainID 和来源群组。向协商功能位 8 的目标边缘发送 Downstream 时,inner Type 4/5 的 DraARLv1 Reserved 携带 source_group_id;发往旧节点前必须清零,避免旧客户端误解保留字段。

边缘本地 fan-out 同样按 Session 去重,并按接收客户端能力分别发送带来源字段或 Reserved 为 0 的帧。一个已认证 UDP 端点不能安装两个不同 Session;边缘拒绝冲突 grant 后会通过 DeviceSessionReport 通知中心撤销刚签发的入口。

6.3 切换与恢复

路由增量必须原子替换 group_id/domain_id/rx_group_ids/rx_domain_ids。节点切换时只迁移目标现代实例,其他同账号 Session 保持原节点。控制链重连的 DeviceSessionConfirmItem 必须同时证明 ghost_session_id、client_instance_id、Owner、SSID、DevModel、旧 Session、旧控制会话和 recovery_ticket;另一个 NodeID 不能冒领该幽灵 Session。

恢复票据使用部署中稳定的 JWT 密钥做域分离 HMAC,只包含恢复所需身份,不包含 JWT 或设备密码。票据与两分钟短期授权同时到期,并在每次 Session 续租、重确认后轮换。中心重启后用票据恢复同一个 ghost_session_id 和 session_tag,但路由、用户启用状态和审核状态始终从当前数据库重新读取;票据不能保留后来已撤销的频道权限。

中心永久失去边缘后会移除实时路由,并在 SessionRecoveryWindowSeconds 内等待同一节点重新确认。窗口到期才调用幽灵 Session 清理;成功确认会取消对应清理任务,不影响同账号兄弟 Session。

反复控制链抖动后,中心的 Session 所有权、幽灵索引、节点计数和路由投影必须收敛到当前控制会话,旧断连回调与旧恢复计时器不得撤销新 Session。网络分区超过边缘本地 grace 后,边缘必须清空 Session、身份/tag 索引和未完成控制请求;控制链恢复时不得无认证复活已过期 Session,客户端重新认证后才建立新的短期授权。

7. 滚动升级与回滚

推荐顺序:

  1. 备份 MySQL,执行兼容数据库迁移;新增字段和表不会破坏旧服务端读取。
  2. 先升级中心。新中心与旧边缘只协商功能位交集;旧边缘仅继续承载实体设备。
  3. 逐个升级边缘并确认节点详情中的协议版本、功能位、投影 ACK 和 UDP data bind 正常。
  4. 最后发布 Web 和原生客户端。只有连接到已同时协商功能位 8、9 的边缘时才发送版本化幽灵认证。
  5. 观察 Session 数、路由 ACK、会话确认拒绝、无效 session tag、fan-out 去重和写队列指标后再扩大客户端覆盖。

回滚时先关闭幽灵功能入口,再回滚边缘,最后回滚中心。不要删除 ghost_client_preferences、订阅关系、消息字段或复合索引,保留它们可避免再次升级时丢失客户端路由。若只有单个边缘异常,可将其回滚为旧版;该节点会拒绝所有幽灵 Session,但仍可承载标准实体设备。

8. 安全与资源隔离

  • 首次注册 token 只用于换取长期节点身份;identity 文件不得写入日志或公开接口。
  • 管理员轮换凭据时,中心先原子安装新凭据并在有限宽限期内保留旧凭据哈希。在线边缘通过 TLS 收到新凭据,必须先原子写入 identity 文件再确认;中心只有收到确认才报告在线下发成功。离线节点需使用仅显示一次的响应手工更新 identity。
  • 吊销操作同时清除注册、当前和宽限期凭据并递增凭据世代,随后断开当前会话;单独的强制下线只重置连接,不吊销仍有效的凭据。
  • 数据地址只能通过 TLS 下发的随机挑战和 UDP HMAC 证明绑定或重绑,普通中继包不能改变地址。
  • 有效 Type 0 绕过普通设备 IP 限速,但仍受独立的每节点 PPS、带宽、队列、会话数和全局节点数上限约束。
  • HMAC 失败、身份不符、过期、重放、未绑定地址、绑定拒绝、队列满和硬限额分别计数。
  • inner packet 只允许规范化后的 Type 4/5,设备密码和 JWT 不进入 UDP 中继载荷;Type 3 只走 TLS 控制面。
  • 幽灵恢复票据只在已认证 TLS 控制面流转,不进入 UDP Relay、日志、指标标签或管理 API;篡改、过期、跨 NodeID 和跨旧控制会话的票据全部拒绝。

相关配置见部署与配置,性能数据见UDP 转发压力测试。