cjdns DJC 分层模型深度解析:从 LayerA 到 LayerE 的报文封装、加密边界与源码印证

发布时间:2026/10/13 6:34:01
cjdns DJC 分层模型深度解析:从 LayerA 到 LayerE 的报文封装、加密边界与源码印证 网络网络安全【免费下载链接】cjdnsAn encrypted IPv6 network using public-key cryptography for address allocation and a distributed hash table for routing.项目地址https://gitcode.com/gh_mirrors/cj/cjdns点击查看免费下载cjdns 是一个使用公钥密码学进行地址分配、以分布式哈希表DHT实现路由的加密 IPv6 网络。本文围绕仓库中的架构设计文档 doc/djc_layer_model.md 展开系统讲解 cjdns 数据报文的五层封装模型LayerALayerE、每一层的可见性边界与加密职责并结合 wire/、net/、crypto/ 下的源码实现逐层印证。读完本文你将能够理解 cjdns 报文从「UDP 链路」到「用户数据」之间每一层头部的职责、长度与替换规则也能解释为什么路由器必须等待加密会话进入 ESTABLISHED 状态之后才能转发报文。文档定位一份设计蓝图而非实现说明doc/djc_layer_model.md是一份协议分层设计文档开篇明确标注 This is not implemented yet尚未实现并且被 doc/index.md 归入 Random notes, work-in-progress随机笔记、进行中一栏属于对 cjdns 核心架构的规划性描述。不过从当前仓库的源码结构可以确认文档中描述的大量设计DataHeader、RouteHeader、加密会话状态机、控制报文等都已经在代码中落地因此它实际上是一份理解现行协议栈的权威蓝图值得逐层拆解。cjdns 的报文在从发送方到接收方的旅程中会被不同角色直接通信的 peer、路径上的 switch、中间 router、最终端点以不同视角观察。DJC 模型的核心思想就是把报文按「谁需要看到什么」切成五层层名称主要头部可见范围加密性质LayerA点对点链路层UDP/Ethernet 帧 CryptoAuth仅直接通信的两个 peer链路级逐跳LayerBSwitch 转发层SwitchHeader路径上所有 switch 及路径两端 router明文LayerC路由器间层CryptoSessionHeader转发该包的 router逐跳加密LayerD路由层RouteHeader转发 router 与最终端点被 LayerC 保护LayerE数据层CryptoSessionHeader DataHeader仅 sender 与 recipient端到端加密下面从下往上逐层展开。LayerA点对点链路层LayerA 负责两个直接通信的 peer即物理或逻辑上相邻的节点之间的传输。文档强调了两点特性本层只对直接通信的两个 peer 有意义层内任何信息都不会被原样传递给路径上的下一跳本层必须向所有更高层提供报文长度信息packet length这是上层能够解析报文边界的前提。虽然传统实现中这一层包含 UDP 或 Ethernet 头但文档明确说明任何形式的 framing 与点对点传输手段都是可接受的。文档给出的三种 LayerA 形态UDPInterface: [ IP ][ UDP ][ CryptoAuth ] ETHInterface: [ ETH Header ][ CryptoAuth ] Direct over phy (future): [ SyncMagic ][ Length ][ CryptoAuth ]其中 UDP 形态在源码中对应 interface/UDPInterface.h接口由AddrIface_t泛化而来数据面 socket 负责收发封装后的报文另可创建 beacon socket 用于广播发现ETHInterface 对应 interface/ETHInterface.h第三种 Direct over phy物理直连含同步魔数与长度字段则被标注为未来方案。注意无论哪种形态CryptoAuth 头都紧随链路头之后——这是链路两端节点之间互认证、加密的基础。可以推断文档字节统计中 LayerA 的[ CryptoAuth ] 20对应旧版 CryptoAuth 运行期报文头大小4 字节 nonce 16 字节 Poly1305 认证标签完整的 120 字节结构见 wire/CryptoHeader.hCryptoHeader_SIZE 120仅握手阶段使用。LayerBSwitch 转发层LayerB 是Switch 层其可见范围是路径上的所有 switch以及路径两端的 router。当 router 把报文继续转发出去时本层的头部会被替换为新的正如每个 IP 路由器都会重写 Ethernet 头一样因此 switch 只负责按本层信息转发不关心更高层。本层只包含一个头部[ SwitchHeader ]SwitchHeader 在 wire/SwitchHeader.h 中定义固定 12 字节SwitchHeader_SIZE 12字段如下label_be8 字节大端switch 决定把报文送往哪个方向的依据congestAndSuppressErrors高 7 位是拥塞指示congest最低 1 位是 suppressErrors 标志——错误报文会置位该标志防止错误消息再次触发错误消息形成风暴。注释特别说明v8 之前该字节整体是 message type仅定义了 0data、1control 两种v8 起被拆分为拥塞位 抑制位v8 节点通过将 congest 置非零来与旧节点区分versionAndLabelShift高 2 位是发送该报文的 switch 版本低 6 位是 labelShift——即 label 在逐级切换过程中被右移的位数v11 起维护该值更老的 switch 不会更新它trafficClass_be流量类别编号0xffff表示 unclassed。注释中说明规划中的流量分级会为不同类别提供不同的带宽配额超载时优先丢弃超出配额的部分但所有带宽仍允许突发burstable。LayerC路由器间加密层LayerC 是Inter-Router Layer路由器间层只对将要转发报文的 router 有意义。本层有两个关键设计加密边界本层以 CryptoSessionHeader 开头因此本层及本层以下的所有数据switch 都无法访问——switch 只能看到 LayerB 的明文 SwitchHeader以及 LayerC 开头的密文MTU 稳定性约束由于 CryptoSessionHeader 的宽度取决于所代表 CryptoAuth 会话的状态见后文run 报文 24 字节、setup 报文 124 字节宽度是波动的。为了防止报文 MTU 波动一个 router 只有在与下游 router 的 CryptoAuth 会话进入ESTABLISHED状态之后才允许把报文转发给那个 router。[ CryptoSessionHeader ]ESTABLISHED 状态在源码中有明确对应加密会话由 crypto/Ca.h 封装OLD_CA分支下直接#error Old CA is nolonger supported说明旧版 CryptoAuth 已被淘汰现行实现为 Rust 侧Rffi_CryptoAuth2。会话状态机包含六个状态INIT → SENT_HELLO → RECEIVED_HELLO → SENT_KEY → RECEIVED_KEY → ESTABLISHEDCa_stateString()提供了这些状态的字符串表示测试文件 crypto/test/CryptoAuth_test.c 也对会话建立与 ESTABLISHED 状态下的行为进行了验证。LayerC 控制报文分支未加密为了让 switch 能够发送错误与其他控制消息LayerC 存在一个不含加密数据的分支在原本放置 CryptoSessionHeader 的位置放入四个字节0xffffffff其后紧跟一个 Control 报文详见 wire/Control.h。这里有一段耐人寻味的设计在 CryptoSessionHeader 语义中0xffffffff原本表示「在不知道对端密钥的情况下发起 CryptoAuth 会话」的意图但在 LayerC 发起会话而不掌握对方密钥是非法的router 之间必须互知公钥因此这个值被复用为「其后是 Control 报文」的标记不会产生歧义。wire/Control.h 定义了控制报文的通用头2 字节 checksum对 checksum 字段置零后的整个控制报文求一的补码校验和 2 字节类型Control_Header_SIZE 4以及 12 种消息类型类型宏用途2Control_ERROR错误报文回显引发错误的报文的 SwitchHeader 与 handleControl_Error_HEADER_SIZE 4最大 256 字节3Control_PING交换机 ping魔数0x09f91102携带版本与最多 256 字节不透明数据4Control_PONGpong与 ping 同构魔数0x9d74e35b5/6Control_KEYPING/Control_KEYPONG请求/回复节点公钥调试用魔数0x01234567/0x89abcdef7/8Control_GETSNODE_QUERY/REPLY查询/通告 supernode 信息key、路径、链路速率 kbps 估计等魔数snoq/snor9/10Control_RPATH_QUERY/REPLY反向路径查询/回复魔数rpaq/rpar11/12Control_LlAddr_QUERY/REPLY链路层地址UDP4/UDP6/Other查询/回复魔数llaq/llar类型 0、1 未在 Control.h 中定义——这与 LayerB 中「v8 之前 SwitchHeader 字节 8 曾作为 message type0data、1control」的历史设计相衔接。LayerD路由层LayerD 是Routing Layer同时面向两类角色转发报文的 routerrouter 借助本层信息决定把报文送往哪个方向最终端点端点可以利用本层放置的数据与中间 router 通信例如发起控制查询router 也可以借助本层向端点回传信息。本层包含[ RouteHeader ]文档特别注明在 v9 之前的版本中RouteHeader 的位置由 IPv6 头替代。这一点与源码相互印证——wire/RouteHeader.h 中的注释明确写道This header is never sent on the wire, it is only used for communicating to the SessionManager which node you wish to communicate with and what path the packet should take.该头从不直接发送到线上仅用于与 SessionManager 通信指明要与哪个节点通信、报文应走哪条路径。RouteHeader 的字段包括publicKey[32]对端节点公钥未知时可填 32 字节零SessionManager 会在 SessionTable 中查找或缓冲报文并触发一次搜索struct SwitchHeader sh要使用的 switch 头其中 label_be 未知时可置零version 会被自动设为节点当前版本version_be对端协议版本未知为 0flagsINCOMING1该头表示的是报文的源而非目的地此时 ip6、publicKey、switch label 均指向源、CTRLMSG2控制消息、PATHFINDER4路径查找相关ip6[16]对端 IPv6 地址必填。RouteHeader 的实际使用集中在 net/SessionManager.c发送方向上SessionManager 把 SwitchHeader 作为关联数据associated data参与加密后构造 RouteHeader填入对端公钥、ip6、label并压入报文见第 340379 行附近接收方向上收包时Message_epop弹出 RouteHeader 并移入 additional data 供上层使用第 726740 行附近。注意文档字节统计中的 RouteHeader 为 20 字节而当前源码中RouteHeader_SIZE为 56 SwitchHeader_SIZE12共 68 字节——前者是设计文档给出的简化视图后者才是当前实现的真实尺寸。LayerE数据层LayerE 是Data Layer只对发送方sender和接收方recipient有意义受一层端到端的 CryptoAuth 加密保护中间 router 无法访问其中的数据[ CryptoSessionHeader ][ DataHeader ][ TCP/UDP/other ][ users data ]DataHeader 在 wire/DataHeader.h 中定义固定 4 字节DataHeader_SIZE 4受第二层l2加密层保护主要作用是告诉端点内容的协议类型高 4 位版本号DataHeader_CURRENT_VERSION 1通过DataHeader_setVersion()写入低 4 位 1 字节未使用2 字节contentType大端。内容类型取值定义在 wire/ContentType.h0255保留给 cjdns/IPv6 报文地址落在FC00::/8内取值直接来自 IPv6 头的 nextHeader 字段例如ContentType_IP6_TCP6、ContentType_IP6_UDP17、ContentType_IP6_ICMPV658256ContentType_CJDHTbencoded 格式的路由器间 DHT 消息257ContentType_IPTUNIP 隧道报文2580x7fff保留0x8000 起ContentType_AVAILABLE可自定义类似端口号供 cjdns 子系统之间约定使用ContentType_CTRL 0xffff 1特殊类型永远不会出现在线上代表未加密的控制帧。DataHeader 的实际构造与分发逻辑在 net/UpperDistributor.c出站时构造 DataHeader 并DataHeader_setVersion(CURRENT_VERSION)、DataHeader_setContentType(ContentType_IP6_UDP)入站时弹出 DataHeader 读取 contentType 后按类型分发——ContentType_IP6_UDP等 IP 类型走 TUN 适配器ContentType_CJDHT走 DHT 路径ContentType_IPTUN走隧道ContentType_CTRL走控制面。直接路径优化0xfffffffe如果发送方经由 switch fabric 使用直接路径direct path到达接收方——即二者之间没有需要解密重封装的中间 router——那么 LayerE 的 CryptoSessionHeader 会被省略并在其位置放置大端形式的四个字节0xfffffffe。此时发送方的身份由 LayerC 的 CryptoSessionHeader 来确定因为在直接路径下LayerC 的逐跳会话实质上就是 sender 与 recipient 之间的端到端会话重复加密没有意义用0xfffffffe标记即可让接收方从 LayerC 会话中取得发送方身份。CryptoSessionHeader124/24 双形态文档明确指出仓库中没有 CryptoSessionHeader.h当前源码确实不存在该文件因此其性质完全由文档定义。CryptoSessionHeader 有两种形态setup会话建立报文头124 字节run运行期报文头24 字节。单个报文属于哪种形态由前四个字节判定若前 4 字节按大端整数解读≥ 4 且不等于0xffffffff则该报文是 run 报文前 4 字节是handle否则是 start 报文前 4 字节是CryptoAuth 会话状态。这一规则与旧版 wire/CryptoHeader.h 的 nonce 字段注释一脉相承Numbers one through three are interpreted as handshake packets, UINT32_MAX is a connectToMe packet and anything else is a nonce in a traffic packet.13 为握手包、UINT32_MAX为 connectToMe、其余为流量报文 nonce。同时net/SessionManager.c 第 29 行的注释 Handle numbers 0-3 are reserved for CryptoAuth nonceshandle 编号 03 保留给 CryptoAuth nonce也印证了 run 报文 24 字节形态4 字节 handle 20 字节加密载荷头与 setup 124 字节形态在实现中的对应关系。完整报文字节布局文档在末尾给出了一个完整的报文封装字节统计设计视图自上而下即自外而内[ IP ] 20 [ UDP ] 8 [ CryptoAuth ] 20 [ SwitchHeader ] 12 [ CryptoSessionHeader ] 24 [ RouteHeader ] 20 [ CryptoSessionHeader ] 24/124 [ DataHeader ] 4 [ TCP/UDP/other ] [ users data ]逐项解读[ IP ] 20[ UDP ] 8LayerA 的 UDP 链路头示例取 IPv4 头长 20 字节[ CryptoAuth ] 20LayerA 的链路级加密头运行期形态[ SwitchHeader ] 12LayerB对应 wire/SwitchHeader.h 的SwitchHeader_SIZE 12[ CryptoSessionHeader ] 24LayerC 的路由器间逐跳加密头run 形态[ RouteHeader ] 20LayerD。如前所述设计视图为 20 字节当前源码 wire/RouteHeader.h 实际为 68 字节且不直接上线[ CryptoSessionHeader ] 24/124LayerE 的端到端加密头run 为 24 字节、setup 为 124 字节宽度随会话状态变化——这正是 LayerC 要求 ESTABLISHED 后才转发的根本原因[ DataHeader ] 4LayerE 内容类型指示对应 wire/DataHeader.h 的DataHeader_SIZE 4之后才是 TCP/UDP 等上层协议与用户数据。v9 演进对照文档多处提到 v9 前后的差异整理如下该文档本身即以 v9 为设计基准层v9 之前v9 及以后本文档设计LayerDIPv6 头替代 RouteHeaderRouteHeaderLayerECryptoAuth 头替代 CryptoSessionHeader且无 DataHeaderCryptoSessionHeader DataHeaderLayerE 直接路径CryptoAuth 头直接省略、无替代接收方需比较 LayerD IPv6 头的 source 字段与 LayerC CryptoSessionHeader 中确定的发送 router 身份以0xfffffffe四字节占位身份统一由 LayerC 确定这一演进在源码中也留有痕迹wire/CryptoHeader.h 是旧版 120 字节握手头的定义而 crypto/Ca.h 中#error Old CA is nolonger supported表明旧 CryptoAuth 实现已被 Rust 侧 CryptoAuth2 全面取代net/SessionManager.c 与 net/UpperDistributor.c 则已经是 RouteHeader/DataHeader 的现行处理者。总结五层模型与安全边界DJC 分层模型的核心价值在于它精确划定了谁在何时能看到什么switch只能看到 LayerB 的 SwitchHeader 与 LayerC 的密文起始天然无法窥探路由与数据内容中间 router因持有逐跳会话密钥可解密 LayerC、读取 LayerD 的 RouteHeader 完成转发但无法触碰 LayerE 的端到端密文最终端点持有端到端会话密钥才能解开 LayerE 看到 DataHeader 与真正的用户数据LayerC 的0xffffffff控制分支为 switch 提供了合法的、未加密的错误与控制通路CryptoSessionHeader 的 24/124 双形态与「ESTABLISHED 后才转发」的约束共同保证了端到端 MTU 的稳定。对于希望深入理解 cjdns 协议栈的读者仓库中还提供了配套资料doc/Whitepaper.md原始白皮书、doc/cjdns/anatomy.mdcjdroute 结构剖析、doc/security_specification.md安全规范以及正文中引用的各 wire 头文件与 net/SessionManager.c、net/UpperDistributor.c、crypto/Ca.h 等实现可按需对照阅读。赞分享网络网络安全【免费下载链接】cjdnsAn encrypted IPv6 network using public-key cryptography for address allocation and a distributed hash table for routing.项目地址https://gitcode.com/gh_mirrors/cj/cjdns点击查看免费下载相关推荐PaddleSpeech CTC 解码器 SWIG 封装模块深度解析从 Python 接口到 C 底层实现PaddleSpeech CTC 解码器 SWIG 封装模块深度解析从 Python 接口到 C 底层实现 本篇文章以 PaddleSpeech 仓库中的人工智能语音音频CANN/asc-devkituint16转uint32数据类型转换APIasc_uint162uint32 产品支持情况 ! npu950 id1 Ascend 950PR/Ascend 950DT支持 ! end id人工智能深度学习算子库CANNAscendParamiko Packetizer 源码解析SSHv2 底层报文协议与加解密实现Paramiko Packetizer 源码解析SSHv2 底层报文协议与加解密实现 SSHSecure Shell协议的传输层报文封装packet f后端网络通信密码学上一篇冒险岛地图编辑器终极指南免费工具让你快速打造专属游戏世界下一篇如何在Windows电脑上轻松运行安卓应用3种轻量级安卓模拟器方案对比创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询