网络网络安全【免费下载链接】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点击查看免费下载cjdnsCJDNSCaleb James DeLisle 的加密网状网络套件是一个基于公钥密码学的 IPv6 网状网络实现它用公钥哈希自动生成节点地址、用分布式哈希表完成路由并对全部流量做端到端加密。本文以仓库根目录 doc/README.md 为骨架结合仓库内源码、工具与配置文档系统讲解 cjdns 的加密机制、地址分配算法、混合拓扑设计、加密验证与路由握手流程并给出加入 Hyperboria 测试网的实际配置步骤帮助读者理解这套无需信任中转节点的组网方案背后究竟如何运作。一、Hyperboria 测试网与 cjdns 的定位原文档开篇首先定义了 Hyperboria 与 cjdns 的关系Hyperboria 是一个完全由 cjdns 节点构成的测试网络test network built of cjdns nodes而cjdns 本身则是一套实验性的加密网状网络套件experimental, cryptographic mesh networking suite。二者互为表里cjdns软件层提供加密隧道、地址分配、路由与转发等全部协议实现仓库中的核心代码分布在 crypto/、dht/、net/、switch/ 等目录。Hyperboria网络层由运行 cjdns 的节点自愿互联而成任何安装了 cjdns 并完成对等连接peering的节点都可以加入。原文档强调的 cjdns 核心价值可概括为四点后文将逐一展开端到端加密Encryption、基于公钥哈希的地址分配Address Allocation、混合拓扑Hybrid topology、加密验证与路由Cryptographic verification and routing。二、端到端加密密钥对、SALSA20 流密码与前向保密2.1 加密模型cjdns 为节点间的每条链路建立加密隧道其核心设计见 doc/README.md 的 Encryption 一节每个节点持有一对私钥/公钥private/public keypair隧道内传输的所有数据都使用SALSA20 流密码Salsa20 stream cipher加密由于每次会话都会协商新的临时密钥协议能够提供完美前向保密perfect forward secrecy——即使节点长期私钥日后泄露也无法解密此前捕获的历史会话流量。从仓库源码看这一设计在现代实现中体现为 Rust 侧rust/cjdns_sys/src/crypto/crypto_auth.rs中引用的curve25519xsalsa20poly1305组合Curve25519 密钥交换 XSalsa20 流密码 Poly1305 消息认证C 侧通过 crypto/Ca.h 封装调用Rffi_CryptoAuth2_*系列接口。也就是说当前实现使用 NaCl 风格的curve25519xsalsa20poly1305密码套件在保证原文档所述 Salsa 系流密码加密的同时额外叠加了 Poly1305 认证防止密文被篡改。2.2 握手与会话状态机建立加密连接需要一次密码学握手。协议定义在 wire/CryptoHeader.h 中握手包120 字节struct CryptoHeader携带会话状态nonce、认证挑战Auth Challenge、24 字节握手随机数handshake nonce、永久公钥、Poly1305 认证器以及加密后的临时公钥encryptedTempKey。握手流程分为 hello 包与 key 包两类发起方发送hello 包含自己的永久公钥与临时公钥响应方回送key 包含自己的临时公钥双方据此协商会话密钥之后双方即可互发加密数据包。crypto/Ca.h 中定义的会话状态机完整刻画了这一过程状态含义INIT会话初始状态尚未发送任何握手包SENT_HELLO已发送 hello 包等待对方响应RECEIVED_HELLO已收到对方 hello 包SENT_KEY已发送 key 包作为 hello 的回应RECEIVED_KEY已收到 key 包可开始发送数据包ESTABLISHED会话建立完成进入加密数据传输阶段值得注意的是握手过程中每个会话都会生成临时密钥对temp keyhello 包中的永久公钥用于身份验证而加密临时公钥用于实际会话加密。临时密钥只存活于本次会话这正是前向保密得以实现的原因——即便长期私钥泄露攻击者也无法还原已经废弃的临时会话密钥。三、地址分配双重 SHA512 哈希与 FC00::/8 前缀3.1 地址生成算法cjdns 最富特色的设计之一是节点 IPv6 地址直接由公钥推导而来doc/README.md 的 Address Allocation 一节分配给 TUN 接口的 IPv6 地址由你的公钥的 SHA512 哈希的 SHA512 哈希的前 16 字节组成。即对公钥执行两次 SHA512 哈希取结果的前 16 字节作为 128 位 IPv6 地址。源码 crypto/AddressCalc.c 中AddressCalc_addressForPublicKey()的实现与此完全吻合bool AddressCalc_addressForPublicKey(uint8_t addressOut[16], const uint8_t key[32]) { uint8_t hash[64]; Rffi_crypto_hash_sha512(hash, key, 32); // 第一次 SHA512 Rffi_crypto_hash_sha512(hash, hash, sizeof hash); // 第二次 SHA512 if (addressOut) { Bits_memcpy(addressOut, hash, 16); // 取前 16 字节作为 IPv6 } return AddressCalc_validAddress(addressOut); }3.2 FC00::/8 前缀的强制由于公钥哈希是均匀分布的直接取前 16 字节得到的地址通常不以fc开头。为此 cjdns 采用**暴力搜索brute force**方式生成密钥对反复随机生成私钥、计算公钥与地址直到得到的地址首字节为FC即落在 fc00::/8 网段内。crypto/AddressCalc.h中定义了可配置的地址前缀宏默认为0xfc前缀长度 8 位可通过编译期宏覆盖AddressCalc.c中的AddressCalc_validAddress()用位掩码方式校验地址是否命中该前缀bool AddressCalc_validAddress(const uint8_t address[16]) { uint64_t significant_bits; Bits_memcpy(significant_bits, address, sizeof(uint64_t)); return (significant_bits ADDRESS_PREFIX_MASK) ADDRESS_PREFIX_U64; }密钥生成的核心循环见 crypto/Key.c 的Key_gen()for (;;) { Random_bytes(rand, privateKeyOut, 32); // 随机私钥 crypto_scalarmult_curve25519_base(publicKeyOut, privateKeyOut); // 派生公钥 // Brute force for keys until one matches FC00:/8 if (AddressCalc_addressForPublicKey(addressOut, publicKeyOut)) { return 0; } }由于fc前缀占 8 位命中概率约为 1/256因此生成速度很快对普通机器而言只是多试几次的开销。3.3 为什么使用 fc00::/8原文档指出fc00::/8 地址空间已被 IANA 分配为 Unique Local AddressULA唯一本地地址空间因此这些地址不会与 ICANN 分配的全球 IPv6 地址或其他常规互联网操作冲突。cjdns 借用了这一保留段作为自身网络的地址池从而天然避免与公网 IPv6 地址混淆。这也是 doc/README.md 中这些地址不应与常规互联网操作冲突一句的由来。3.4 配套工具makekeys / publictoip6 / privatetopublic仓库在 contrib/c/ 提供了一组与地址分配配套的小工具可作为理解上述算法的实操样例makekeys持续生成 cjdns 密钥对并输出到 stdout每行格式为私钥(hex) IPv6地址 公钥(Base32以.k结尾)。用法makekeys | head -20 keys.txt可批量预生成密钥见 contrib/doc/makekeys.md。其实现见 contrib/c/makekeys.c调用Key_gen()生成满足 FC 前缀的密钥再用Hex_encode/Base32_encode/AddrTools_printIp格式化输出。publictoip6给定以.k结尾的 52 字符 Base32 公钥反解出对应 IPv6 地址publictoip6 public key见 contrib/doc/publictoip6.md。实现见 contrib/c/publictoip6.c内部调用Key_parse()完成 Base32 解码与地址校验。privatetopublic从标准输入读取 hex 私钥最多 64 字符推导出公钥与 IPv6。由于私钥极为敏感官方手册建议用 heredoc 方式输入而非命令行参数避免密钥泄露到进程列表或 shell 历史中见 contrib/doc/privatetopublic.md。四、混合拓扑friend-of-a-friend 与 NAT 穿透4.1 设计初衷cjdns 在设计上面向friend-of-a-friend朋友的朋友拓扑doc/README.md 的 Hybrid topology 一节。它构建的是一个overlay network叠加网络在底层互联网之上再抽象出一层虚拟网络从而穿透 NAT网络地址转换让网络中每个节点的所有端口都对其他节点可见。原文档对此给出了重要提醒习惯依赖 NAT 保护设备例如家用路由器隐藏内网主机的用户可能会觉得这种设计麻烦——因为在 cjdns 网络内节点的端口默认对所有其他节点开放安全边界不再由 NAT 提供。4.2 信任模型原文档明确表述了 cjdns 的信任模型网络设计之初的预期是每个人只与自己信任的朋友建立对等连接peering但你不需要信任中转中继节点来保证数据包的机密性与完整性——因为所有流量都经过端到端加密如果你希望限制某些服务的访问你有责任自行实施有效的访问控制规则而非依赖网络的物理拓扑。这一零信任中继、自管访问控制的原则是理解 cjdns 安全模型的关键。4.3 链路介质多样性节点之间的链路既可以通过有意的 UDP 链路跨越互联网建立也可以通过以太网、无线接入点、Ad-hoc 临时网络以及各种系统特定的传输与寻址协议建立有意或自动的连接。仓库中对应的实现包括 interface/UDPInterface.cUDP 对等连接与 interface/ETHInterface_linux.c 等以太网接口实现配置层面分别对应UDPInterface与ETHInterface两个接口块详见下文第六节的配置实操。五、加密验证与路由连接即验明正身5.1 连接过程中的密码学授权原文档指出在两个节点之间建立链路包含一个密码学授权cryptographic authorization过程在此之后网络内的其他节点才能与新节点建立连接。结合 crypto/Ca.h 的会话 APICa_newSession、Ca_setAuth、Ca_addUser等可以看出这一过程既包含第 2.2 节所述的临时密钥握手也包含基于共享密码authorizedPasswords中的 password的可选身份认证会话可要求对端提供密码requireAuth密码不匹配或登录名不存在时握手会以AUTH_REQUIRED、UNRECOGNIZED_AUTH等错误码终止见Ca_DecryptErr枚举。5.2 公钥与 IPv6 的绑定验证由于每个节点的公钥与其 IPv6 地址之间存在确定的哈希关系并且这一关系在连接时会被验证原文档给出了一条简洁而有力的结论如果你能通过 cjdns 连接到某个 IPv6 地址并收到响应就可以相当确定响应的节点持有与该 IPv6 对应的私钥。换句话说只要你能连上对端就必然有能力解密你的请求并产生响应——地址伪造在 cjdns 中在密码学意义上不可行。这也意味着 cjdns 的路由天然与身份验证耦合寻址即寻人加密即认证。该地址-公钥对应关系同样被 crypto/test/CryptoAuthFuzz.c 等测试用例反复调用如其中AddressCalc_addressForPublicKey(nodeAAddress, ctx-nodeA.pubKey)的用法印证了从公钥到地址、再到会话建立这条链路的实现闭环。六、实战加入 Hyperboria / 构建 cjdns 网络的配置要点6.1 入门路径原文档How can I get involved 一节给出的参与路径非常朴素先在某个地方安装 cjdns 并亲手运行熟悉它的工作方式同时把遇到的困难、不直观之处或文档缺失记录下来并分享帮助后来者。仓库根目录的 README.md 提供了各平台构建与运行指引配置细节则集中在 doc/configure.md 与 doc/peering.md。6.2 配置文件中的密钥与地址配置文件的顶部包含节点的身份三要素完整示例见 doc/configure.md 的 Your Keys and Address 一节{ // Private key: 机密性与数据完整性都依赖它务必保密 privateKey: 823e4EXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEc70, // 与公钥和 ipv6 地址对应 publicKey: u2jf87mgqlxfzdnywp60z3tx6tkulvgh2nyc2jk1zc69zzt2s8u0.k, ipv6: fcff:a215:1e7b:a4e9:c00d:0813:93b3:7c87, }privateKey加密进出的全部数据必须保护不得外泄publicKey交给对端用于加密数据只有你的私钥能解密ipv6你在 cjdns 网络中的地址由公钥安全哈希生成即第三节所述算法。原文档特别说明publicKey与ipv6字段仅为方便而提供并非必需。若删除它们启动时 cjdns 会用私钥推导出公钥、再用公钥推导出地址三者关系是确定性的——只保留最基础的私钥字段可以避免配置不一致。6.3 入站连接authorizedPasswordsauthorizedPasswords段定义允许哪些密码连接你的节点doc/configure.md 的 Incoming Connections 一节authorizedPasswords: [ {password: zxl6zgxpl4stnuybdt0xlg4tn2cdl5h, user: default-login} ],password对端连接时必须出示的密码应使用足够长且随机的字符串——文档警告当前实现不对密码做密钥派生切勿使用可猜测的弱口令user可选的用户标识运行时peerStats脚本会用它关联对应密码连入的节点便于管理多个对端注释中形如your.external.ip.goes.here:33808:{login: default-login, password: ..., publicKey: ...k}的片段是你要交给朋友、供其发起入站连接的凭据模板。6.4 出站连接connectTo在UDPInterface的connectTo中填写朋友的连接凭据即可主动发起出站连接doc/peering.md 的示例connectTo: { 0.1.2.3:45678: { login: k.alexander, password: thisIsNotARealConnection_1, publicKey: thisIsJustForAnExampleDoNotUseThisInYourConfFile_1.k } }doc/peering.md同时强调连接可以由任意一方发起出站或入站一旦建立流量双向流动。要给朋友入站连接权限你需要提供 5 项信息你的外部 IPv4、配置中的bind端口、对方专属密码、你的公钥、以及他的用户名。6.5 UDP 接口与自动对等发现UDPInterface支持通过 beacon 机制在局域网内自动对等doc/configure.md 的 Connection Interface(s) 一节UDPInterface: [ { bind: 0.0.0.0:33808, // 监听的 IP 与端口 beacon: 2, // 0禁用1仅接收2收发 beaconDevices: [ all ], // eth0、广播地址或 all beaconPort: 64512, // 自动对等必须全网一致 connectTo: {} } ]bind监听对等连接的 IP 与端口beacon0 关闭自动对等1 只接受其他节点的 beacon 并尝试回连2 同时广播与接收 beaconbeaconDevices参与广播的设备名或广播地址列表all表示使用所有接口的广播地址beaconPortbeacon 消息使用的 UDP 端口所有自动对等节点必须相同。此外还有ETHInterface用于以太网直连bind为设备名如eth0connectTo以 MAC 地址作为键以及router段中的dnsSeedsDNS TXT 记录自动获取对端与超级节点、supernodes、publicPeer等面向全网互联的配置项均可查阅 doc/configure.md 获取完整参数说明。6.6 管理接口与安全选项配置中还有两个常被忽略但对运维重要的段落doc/configure.mdadmin管理 RPC 接口bind默认127.0.0.1:11234仅本地绑定时可将password设为NONE简化默认配置contrib/ 下的大量脚本如 peerStats、sessionStats都依赖此接口与 cjdns 交互。security运行期权限收紧选项例如nofiles将打开文件数设为 0阻断大多数依赖文件的漏洞利用路径与{setuser: nobody}启动并获取资源后降权到指定用户。七、参与贡献与文档生态原文档最后给出了贡献指引阅读 doc/contributing.md 了解项目接受贡献的政策。该文档所在的 doc/ 目录本身就是一个面向 Hyperboria 的文档项目涵盖 cjdns 内部机制、运维者文化与最佳实践、本地网格meshlocal资源以及入门读物等主题并欢迎多语言翻译原 README 亦提供 Español 版本仓库内还有多语言 README。报告 bug 时可参考 doc/bugs/reporting.md 与 doc/bugs/policy.md。八、小结从 doc/README.md 出发结合仓库源码可以看到 cjdns 的设计闭环身份即地址公钥经双重 SHA512 哈希并暴力筛选出 fc00::/8 前缀节点地址与身份在密码学上强绑定crypto/AddressCalc.c、crypto/Key.c加密即默认Curve25519 XSalsa20/Poly1305 的端到端加密隧道配合每次会话的临时密钥实现前向保密crypto/Ca.h、wire/CryptoHeader.h路由即认证加密握手与授权过程保证连得上即验明正身叠加网络可穿透 NAT构建出 friend-of-a-friend 的分布式网状网络配置即实践通过connectTo、authorizedPasswords、UDPInterface与ETHInterface等配置项即可完成入站/出站对等加入 Hyperboria 或自建加密 mesh。这套地址由密钥决定、流量全程加密、中继不可窃听篡改的设计使 cjdns 成为学习加密组网与分布式路由不可多得的参考实现——安装一个节点亲手体验再对照本文的源码路径深入阅读是理解它最有效的方式。赞分享网络网络安全【免费下载链接】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点击查看免费下载相关推荐NixOS 集成 Yggdrasil端到端加密 IPv6 网格网络模块配置实战指南NixOS 集成 Yggdrasil端到端加密 IPv6 网格网络模块配置实战指南 Yggdrasil 是一个早期阶段的端到端加密、自组织 IPv6 网格网络包管理器操作系统FunASR Android 移动端部署实操指南3 步在手机上跑通实时语音识别FunASR Android 移动端部署实操指南3 步在手机上跑通实时语音识别 想在手机上做实时语音识别开会记纪要、开车转写、走路记想法场景很诱人可让手语音音频人工智能大模型模型推理服务本地部署Security-101 网络零信任架构实战指南网络分段、端到端加密与 SASE 落地Security 101 网络零信任架构实战指南网络分段、端到端加密与 SASE 落地 本篇技术指南以 Security 101 课程第 3.2 课 3.2网络安全教程文档上一篇k-skill 的 ticket-availability 技能实战YES24 / インターパークInterpark公演日程与等级余座查询的 CLI 实现与运行机制下一篇Security-101 安全入门常见网络安全威胁全景解析攻击动机、八大威胁类型与 MITRE ATTCK 框架创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?