- 网络
- 网络安全
【免费下载链接】cjdns
An encrypted IPv6 network using public-key cryptography for address allocation and a distributed hash table for routing.
cjdns 是一个利用公钥加密分配 IPv6 地址、并以分布式哈希表(DHT)进行路由的加密 Mesh 网络实现。本文以仓库内 doc/cjdns/changelog.md 为骨架,逐条还原 2015 年 1 月 v13、v14、v15 三个滚动版本的变更全貌,并结合仓库源码(client/Configurator.c、dht/dhtcore/NodeStore.c、net/InterfaceController_admin.c、client/cjdroute2.c 等)验证每一条变更背后的真实实现。读完本文,你将掌握:cjdns 历史版本的启动流程竞态修复、ETHInterface 二层自动组网机制的演进、Admin API 认证策略的调整、DHT 搜索(SearchRunner)的引入,以及 NodeStore 路由选择策略的取舍逻辑。
一、文档定位:crashey 分支、master 滚动发布与 Version.h
changelog 开篇明确了 cjdns 的版本管理模型:
- crashey 分支用于日常开发,处于不稳定状态;
- master 分支是滚动发布(rolling release),即没有一个冻结的"正式版",master 上的代码本身就是交付物;
- 每个版本条目都记录了
crashey since:与master since:两个提交哈希及提交信息,方便追溯该版本内容的实际落地时间点。
文档特别提到 util/version/Version.h(当前仓库中对应文件为 util/version/Version.c 与 util/version/Version.h),版本号主要由它承载。文档记录的"当前状态"提交为5fa245c - remove check code (Tue Feb 3 23:25:10 2015 +0100),说明这份 changelog 撰写于 2015 年 2 月初,v13–v15 均集中于 2015 年 1 月,属于同一个月内高频迭代的产物——这也解释了为何三个版本之间存在明显的连续性:v14 修复 v13 引入的 Ethernet 校验和问题,v15 又修复了 v14 时代 peerStats 的段错误。
二、v15:启动竞态修复、工具链补全与 Admin API 免认证化
v15(2015 年 1 月末)是整个 changelog 中信息量最大的版本,涉及启动流程、构建优化、路由记忆、工具链与 Admin API 五个方面。
2.1 Configurator 启动前先 Ping 核心进程
原文档记载:
The configurator now tries to ping the core process before starting to configure it. This might fix a possible race condition during cjdroute startup.
该条目对应的源码实现可以在 client/Configurator.c 中找到完整的证据链:
tryPing()(L695-L706)通过 Admin RPC 调用ping函数,检查响应中的q字段是否为"pong";waitUntilPong()(L720-L732)会循环最多 10 次,每次间隔 200ms(通过Timeout_setTimeout配合EventBase_beginLoop实现),直到收到 pong 为止;若 10 次全部失败,则触发Assert_failure("Failed connecting to core (perhaps you have a firewall on loopback device?)");- 最终在
Configurator_config()(L734 起)的入口处调用waitUntilPong(&ctx)(L754),随后才继续注入authorizedPasswords、执行Security_setUser等配置步骤。
这意味着 v15 之前存在一种竞态:cjdroute 核心进程尚未在 Admin 端口(默认udp://localhost:11234)就绪时,Configurator 已开始写入配置,导致配置丢失或启动失败。v15 通过"先 ping、再配置"的握手机制消除了这一窗口期。
2.2 构建优化旗标与路由记忆
-Ocflag 修复:-O编译优化旗标此前无法正常设置,v15 起可传-O2(面向性能优化)或-Os(面向磁盘空间优化)。这属于构建系统 node_build/builder.js 与 node_build/make.js 所管辖的编译参数传递逻辑,适合嵌入式/低存储场景。- 记住最后已知路由:节点会尝试记住并复用前往某个节点的最后已知路径,而不是每次从头路由。这与 dht/dhtcore/NodeStore.c 中基于 label 的路径缓存机制相关,可减少重复寻路开销。
- 短格式 IPv6 地址支持:工具与配置接受压缩书写形式的 IPv6 地址(如
fc00::1风格),相关解析能力由 util/AddrTools.c 提供。
2.3 工具链迁移与新增
contrib/nodejs/tools/下的工具整体迁移到仓库根目录的 tools/,此后 cjdns 的运维工具统一收口在顶层tools/下;- 新增sessionStats 工具,用于查看会话统计;
- ping 与 traceroute 工具支持解析 DNS 域名,不再只能输入 IPv6 地址;
- 新增search 工具,且 DHT 搜索通过 Admin API 暴露为
SearchRunner_search()。
SearchRunner_search()在源码中的注册位置为 dht/dhtcore/SearchRunner_admin.c,注册时auth参数为true(L161 的Admin_registerFunction("SearchRunner_search", search, ctx, true, ...)),即该操作仍需要认证——搜索属于可能泄露路由信息的敏感操作。
-c选项(设置搜索/ ping 次数)在两个工具的源码中均可找到:
- tools/ping:解析
-c参数作为maxCount,达到上限后停止输出; - tools/search:
-c被解析为搜索次数上限,并传给cjdns.SearchRunner_search(target, count, handleMessage)。
2.4 Admin API 免认证化:NodeStore 查询开放
v15 规定NodeStore_nodeForAddr()与NodeStore_getLink()不再要求认证。源码证据在 dht/dhtcore/NodeStore_admin.c:
Admin_registerFunction("NodeStore_getLink", getLink, ctx, false, ...)(L338,false即免认证);Admin_registerFunction("NodeStore_nodeForAddr", nodeForAddr, ctx, false, ...)(L343)。
这两者分别用于"根据 IPv6 地址查询节点"和"查询两个节点间的链路信息",本质是只读的路由表查询。将其开放给未经认证的调用方,是为了方便网络诊断工具(如 traceroute、pathfinderTree)无需携带密码即可工作。
三、v14:Hidden Peers 修复、ETHInterface 增强与 InterfaceController 重写
v14(2015 年 1 月中)的重点是二层组网稳定性和路由数据正确性。
3.1 Hidden Peers 与 getPeers 数据错误
- Hidden Peers 问题:此前在 switch 层因 ping 被丢弃而导致 peerings 反复抖动(flapping),v14 修复了该问题。"Hidden Peers" 是指已建立对等关系但在路由表中不显式出现的节点,抖动会导致其连接状态不稳定;
- NodeStore_getPeers() 修复:该函数此前总是返回相同的 peers,修复后每次调用能返回正确的、针对给定 label 的邻居列表。对应实现位于 dht/dhtcore/NodeStore.c,它会先按
NumberCompress_bitsUsedForLabel()截断 label 再遍历PeerRBTree收集邻居。
3.2 ETHInterface:二层以太网自动组网
v14 对 interface/ETHInterface_linux.c(及 darwin 变体)做了三项关键增强:
- 绑定
all接口:ETHInterface 可以绑定到all,即在所有网络接口上启用自动对等(auto-peering),从而对运行期间接口的上/下变动更具韧性——某个网口被拔掉或恢复时不会影响其他接口上的对等关系; - 启动时自动 bring up 接口:ETHInterface 启动时会主动将相应网口置为 up 状态;
- switch ping 错误响应位对齐崩溃修复:switch ping 的错误响应在位对齐上存在问题,特定场景下会触发崩溃,v14 修复了该路径。
ETHInterface 的 auto-peering 机制是 cjdns 在同一局域网内零配置互联的关键:多个节点只需连接到同一台交换机(或同一 Wi-Fi),即能通过以太网帧自动发现并建立加密隧道,无需手工配置connectTo。这也是下一节 v13 中--eth生成配置开关的意义所在。
3.3 工具改进与接口控制器重构
- ping 与 pingAll 工具改进:pingAll 现在同时执行 router ping 和 switch ping(switch ping 用于探测 switch 层的可达性与路径质量),配合 net/SwitchPinger.c 工作;
- InterfaceController 重写:重写后的 net/InterfaceController.c 让自定义接口的开发更容易——接口控制器的职责是管理每个对等会话的密钥交换、加密状态与生命周期,重写后新增接口类型只需实现标准的事件回调即可接入;
- 新增流量分析调试文档:即 doc/TrafficAnalysis.md,帮助开发者从流量特征角度调试网络行为。
四、v13:协议兼容断代、Ethernet 长度字段与路由策略注释
v13(2015 年 1 月初)包含一次明确的协议断代和多项基础修复,其中不少决策以源码注释的形式保留至今。
4.1 v11 及以下节点不再受支持
v13 起,运行 v11 及以下版本的节点:
- 仍能与任何其他节点(包括 v13)建立对等连接;
- 但从 v13 开始,它们的流量不再被 switch 转发;
- 它们也不会再进入 v13 节点的路由表。
这是 cjdns 历史上的一次显式协议断代:旧版本节点被保留"能连通、不能路由"的过渡状态,避免瞬间全网分裂,同时推动全网升级。版本号与协议能力之间的对应关系由 util/version/Version.c 维护。
4.2 ETHInterface 线协议增加 payload 长度字段
v13 发现一个真实世界的问题:部分以太网适配器不会剥离发送方追加在报文末尾的校验和(checksum),导致解密器被混淆。修复方式是在 ETHInterface 的线协议中加入 payload 长度字段,使接收方能精确判定有效载荷边界,从而不受尾部校验和干扰。这也是 v14 中"位对齐崩溃修复"的相邻问题——两者都源于以太网帧边界处理。
4.3 NodeStore_getBest() 移除 DHT k-buckets 考量
v13 将 dht/dhtcore/NodeStore.c 中NodeStore_getBest()对 DHT k-buckets 的考量代码注释掉。changelog 引用了源码注释原文:
The network is small enough that a per-bucket lookup is inefficient Basically, the first bucket is likely to route through an "edge" node In theory, it scales better if the network is large.
也就是说:当时网络规模足够小,按桶(bucket)逐桶查找反而低效——第一个桶大概率会经由"边缘"节点绕路;理论上网络变大后按桶查找会更优,因此代码被保留为注释而非删除。当前 NodeStore.c#L1743-L1762 的实现印证了这一取舍:NodeStore_getBest()先尝试NodeStore_nodeForAddr()直接命中目标,若失败则通过getBestCycle()在 keyspace 中寻找更近的合法下一跳,循环上限 10000 次,并不涉及按桶划分的查找。
这是一个值得细读的工程决策案例:当理论最优算法与当前网络规模不匹配时,先以注释形式保留理论、以实际规模为准选择实现。
4.4 Admin API 与配置生成的新能力
InterfaceController_peerStats()现在返回 peer 的protocolVersion字段,且不再要求认证。源码证据:net/InterfaceController_admin.c 中Admin_registerFunction("InterfaceController_peerStats", adminPeerStats, ctx, false, ...)。结合 contrib/doc/peerStats.md 可以理解该输出的字段含义——protocolVersion是判断对端是否还能路由流量(即是否 ≥ v13)的关键指标;cjdroute --genconf新增--eth开关,用于启用 ETHInterface 并打开自动对等。源码证据在 client/cjdroute2.c(帮助文本)与 L645-L646(--eth参数解析后传入genconf(allocator, rand, eth, ...))。生成配置中 ETHInterface 段默认以_disabled_前缀注释,只有加--eth才会生成激活版本(client/cjdroute2.c#L215-L216);- 新增脚本 contrib/bash/peers.sh:
peers.sh user user@example.net <user's ipv6>,一次性把对等密码同时写入配置文件与运行中的进程,免去重启才能生效的旧流程; - Android 的若干小修复;支持在 macOS 主机上为 ARM 交叉编译(对应 cross-do 与 android_do 脚本);contrib/ 下的文档与脚本整体改进。
五、三个版本的演进脉络总结
将 v13–v15 放在一起看,可以提炼出四条清晰的演进主线,这也是 changelog 最值得深挖的资产:
| 主线 | v13 | v14 | v15 | 佐证源码 |
|---|---|---|---|---|
| 启动/配置可靠性 | — | — | Configurator 先 ping 核心再配置 | client/Configurator.c |
| 二层以太网组网 | 线协议加 payload 长度 | 绑定 all、启动 bring up、位对齐崩溃修复 | auto-peering bug 修复 | interface/ETHInterface_linux.c、client/cjdroute2.c |
| Admin API 开放策略 | peerStats 免认证并含 protocolVersion | — | nodeForAddr/getLink 免认证;SearchRunner_search 仍需认证 | net/InterfaceController_admin.c、dht/dhtcore/NodeStore_admin.c、dht/dhtcore/SearchRunner_admin.c |
| 路由选择 | getBest 不再按 k-buckets 查找 | getPeers 返回错误修复、记住最后已知路由 | 短格式 IPv6、search/sessionStats 工具 | dht/dhtcore/NodeStore.c、tools/search |
5.1 Admin API 的认证边界设计
值得单独强调的是:v13–v15 并非简单"放开一切"。三个版本开放的InterfaceController_peerStats、NodeStore_nodeForAddr、NodeStore_getLink都是只读的诊断类查询,而会触发路由搜索行为的SearchRunner_search()始终要求认证。这种"读开放、写与搜索封闭"的边界,至今仍是 cjdns Admin API 的设计基调,读者在 doc/admin-api.md 与各*_admin.c文件的Admin_registerFunction调用中可逐一核对每个函数的auth参数。
5.2 工具链的沉淀
从 v13 引入 traceroute/cjdnslog,到 v15 把工具迁入根目录 tools/ 并加入 sessionStats、DNS 解析与-c次数控制,cjdns 的运维工具集在这一时期完成了从散落到统一的收口。如今 tools/ 下的 ping、search、traceroute、sessionStats、peerStats 等脚本仍可直接运行,配合 contrib/python3/cjdnsadmin 与 tools/lib/cjdnsadmin 客户端库使用。
六、如何在当前仓库中进一步验证
- 版本常量:util/version/Version.c 与 util/version/Version.h 承载协议版本号,配合
NodeStore_getPeers、peerStats输出中的protocolVersion理解协议断代; - Admin 函数注册清单:在
dht/dhtcore/、net/、interface/下搜索Admin_registerFunction,可逐条核对每个 API 的认证要求与参数签名; - 构建与交叉编译:do、cross-do、android_do 对应 v13 提到的 macOS→ARM 交叉编译能力;
-O2/-Os的编译旗标传递逻辑在 node_build/builder.js; - 工具脚本:tools/ping、tools/search、tools/traceroute、tools/sessionStats 可直接阅读
-c、DNS 解析等 v15 特性的实现; - 以太网自动组网:interface/ETHInterface_linux.c 与 interface/ETHInterface_darwin.c 是 v14 各项 ETHInterface 增强的落点,
--eth生成的配置格式见 client/cjdroute2.c。
结语
cjdns 的 v13–v15 是一个典型的"高速迭代 + 显式断代"窗口:一个月内完成了启动竞态修复、二层自动组网加固、路由数据正确性修复、协议版本断代、Admin API 认证边界调整与运维工具链统一。阅读 doc/cjdns/changelog.md 的价值在于,它不仅是变更清单,更是一份浓缩的架构决策记录——尤其是NodeStore_getBest()中"理论留注释、实现随规模"的取舍,以及"诊断接口免认证、搜索接口需认证"的 API 安全边界,这些决策思路对今天构建去中心化网络系统仍有直接借鉴意义。
- 网络
- 网络安全
【免费下载链接】cjdns
An encrypted IPv6 network using public-key cryptography for address allocation and a distributed hash table for routing.
相关推荐
OCCT开源社区指南:如何参与贡献和获取技术支持
OCCT开源社区指南:如何参与贡献和获取技术支持 Open CASCADE Technology OCCT 是一个开源的3D CAD、CAM、CAE软件开发平台
图形学3D建模3D渲染Vitess v12.0.4 版本深度解析:PlannedReparentShard 竞态修复与 UNION 并发改进
Vitess v12.0.4 版本深度解析:PlannedReparentShard 竞态修复与 UNION 并发改进 导读 本文以官方发布说明( change
数据库分布式数据库云原生后端数据存储yaml-validator 技能:Hyper-Extract 如何自动验证模板语法与类型
yaml validator 技能:Hyper Extract 如何自动验证模板语法与类型 Hyper Extract 是一个用 LLM 将非结构化文本转化为结
人工智能大模型RAGNLP知识图谱CLIMCP 服务AI 技能
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考