改进和稳定 NetBSD 中的 racoon2 IKE 守护进程

Lobsters Hottest 新闻

摘要

Google Summer of Code 2026 项目报告:对 NetBSD 的 racoon2 IKE 守护进程进行现代化改造,添加符合 RFC 规范的 IKE 分片功能、NAT 穿越支持(NAT-OA 载荷与 NAT-T 地址替换)、IPv6 支持以及单元测试框架,使其成为可靠的 IKEv2/L2TP VPN 服务器。

<p><a href="https://lobste.rs/s/wbpt5y/improving_stabilizing_racoon2_ike">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/10/04 13:00

# NetBSD Blog Source: https://blog.netbsd.org/tnf/entry/gsoc2026_racoon2 ## Google Summer of Code 2026 项目报告:改进并稳定 NetBSD 中的 racoon2 IKE 守护进程 (https://blog.netbsd.org/tnf/entry/gsoc2026_racoon2) 2026 年 10 月 3 日 发布者:*Leonardo Taccari* 本报告由 Artem Belan 撰写,作为 Google Summer of Code 2026 项目的一部分。 ## 引言与简介 racoon2 是一个用于交换和安装 IPsec 安全参数的系统。它由一个 IKEv1/IKEv2 密钥交换守护进程、一个安全策略管理守护进程,以及一个基于 Kerberos 的密钥交换守护进程组成。该项目位于 zoulasc/racoon2 (https://github.com/zoulasc/racoon2),正在被现代化改造,以便在 NetBSD 和 Linux 上作为可靠的 L2TP/IPsec 或 IKEv2 VPN 服务器,服务于内置的 Windows、iOS 和 Android VPN 客户端。 本 GSoC 项目的目标是逐项处理那份 `TODO` 清单:根据相关 RFC 为 IKEv1 和 IKEv2 都正确实现 NAT 穿越;让 IPv6 正常工作,使 racoon2 能够在 IPv4 和 IPv6 下都得到正确测试;清理地址宏的混乱;并构建一个单元测试框架,确保这些修复能够长久保持有效。最终,该守护进程可以在 NAT 设备之后运行,并且无需在配置中使用任何 workaround selector 就能服务于现代 VPN 客户端;IPv6 开箱即用;所有改动都受到自动化测试套件的保护。 所有工作都在 `gsoc2026` 分支 (https://github.com/ssszcmawo/racoon2/tree/gsoc2026) 上进行,并于 2026 年 6 月至 9 月间通过 pull request #13–#39 合并进上游。 ## 完成的工作 ### IKE 分片(RFC 7383) 按照 `TODO` 中的说法,分片代码是"过时/不完整"的:被重新组装的消息可能被守护进程误判,超大数据包则可能导致崩溃。项目成果是为 IKEv1/IKEv2 在发送端和接收端都实现了可靠的 RFC 7383 分片:大型 IKE 消息能够被正确地拆分与重组,超过允许分片大小的数据包会被拒绝并给出清晰的日志信息,而不是导致崩溃;对端之间交换大消息——证书、大型提案(proposals)——不再会悄悄失败或拖垮守护进程。 ### IKEv1 快速模式中的 NAT-OA 载荷(RFC 3947) 在夏季项目开始时,守护进程在输入时会忽略 NAT 原始地址载荷,也从不向对端发送。后果是内核不知道客户端在 NAT 之后实际使用了哪些地址,因此不得不对整个数据包重新计算校验和——速度很慢,也不是 RFC 3947 所规定的做法。现在 NAT-OA 载荷符合 RFC 的结构,会在快速模式中被构造并发送,接收时按位置解析(本机地址在前,对端地址在后),并且对端缺失该载荷会被容忍,而不会被视为错误。原始地址还会被传递给内核,以便它进行增量式校验和修正,而不是全量重算。 ### NAT-T 传输模式下的地址替换(RFC 7296 §2.23.1) 这是整个项目的核心,也是对一个由来已久的 `TODO` 项的直接回应:当路径中存在 NAT 设备时,对端在第二阶段提议的地址与响应方所配置的 selector 不匹配,因此响应方需要添加额外的 selector——这些 selector 只在发起方一侧有效——才能通过 selector 检查;像 `transport_ike_natt.conf` 这样的配置就把它们作为 workaround 携带在内,而来自真实客户端的连接始终很脆弱。 最终行为遵循 RFC 7296 §2.23.1:当启用 NAT-T 且在线路上观察到的地址与配置的 selector 不匹配时,观察到的地址会被替换进协商好的 selector 中,IKEv1 和 IKEv2 均如此。workaround selector 不再需要,而且守护进程现在能够在专用 UDP 端口上正确处理 NAT-T 流量,而不只是处理初始端口上的流量。 ### 配置中的地址宏 按照 `TODO` 的原话,通配地址宏是"许多配置相关 bug 的根源":在 IKEv1 配置中能工作的行为,在 IKEv2 中可能悄悄表现异常;某个宏在部分代码路径中表现为通配符,在另一些路径中却表现为"未知,等我们知道了再说";配置错误被忽略而不是被报告出来。 项目将它们统一为一个单一且一致的通配概念,在所有地方行为相同,同时适用于 IKEv1 和 IKEv2 配置;当地址查找或展开失败时会产生清晰的诊断信息,而不是悄无声息地失败、让用户自己去猜为什么策略从未被安装。 ### 修复 IPv6 支持并默认启用 racoon2 的 IPv6 支持存在多年,但工作得不正常:当接口被配置为使用所有地址时,守护进程仍然表现得好像只存在 IPv4 地址——就像接口被设为只使用 IPv4 一样——而且前缀长度的边界情况也坏了,所以实际上 racoon2 根本无法用 IPv6 进行测试。 在项目期间,这些 bug 都被修复了——地址匹配、Linux 上的接口地址验证、前缀长度处理——IPv6 也变成了一个现代守护进程应有的样子:默认使用,无需记住任何配置开关。项目结束后,同样的配置文件直接就能配合 IPv6 地址使用,配置侧关于 IPv6 的 `TODO` 项也已关闭;剩下只需用真实的 IPv6 流量进行端到端测试。 ### 策略与提案(proposal)协商 在项目开始之前,传输模式的策略是根据通用的 SA 端点生成的,而不是根据为 SA 配置的地址;隧道模式的策略可能引用了错误的端点;而且守护进程是自己组装协商好的 IPsec 提案,而不是接受对端实际提议的内容——这是与真实客户端协商失败的常见原因,因为真实客户端都会带来自己的提案。 现在传输模式和隧道模式的策略都是从配置的 SA 地址生成的,协商出的提案则是根据对端的提案构建的,因此与原生的 Windows、iOS 和 Android 客户端的互操作性不再依赖于本地配置把一切都猜对。 ### IKE 守护进程的单元测试框架 该项目完全没有自动化测试;每次改动都必须靠阅读代码和手动运行守护进程来验证。夏季的最后阶段就花在了改变这一状况上:一个无外部依赖、自包含的小型测试框架现已集成到标准构建中,其测试会在 sanitizers 下运行。 在此之上,四个新的测试程序恰好覆盖了本项目引入的逻辑——NAT 原始地址载荷处理、流量 selector 的地址替换、配置中的通配地址处理、以及清除对端(purge)时所用的地址匹配——并且原有的 crypto 自检也被修复,使得整个测试套件可以干净地通过。 这其重要性超出项目本身:该框架让为守护进程中仍然没有测试的部分添加回归测试变得简单,无论谁来接手都是如此。 ### 文档、样例与 NEWS 文档和示例配置仍然描述着旧的默认值,因此手册与实际发布的行为相互矛盾:它仍然描述旧的 IPv6 行为以及替换之前的 selector workaround。项目将文档和样例与新的默认值同步——IPv6 默认启用、分片自动处理、隧道端点与通配地址的一致使用——并添加了一条 `NEWS` 条目,为用户和下游打包者总结了 GSoC 2026 的全部工作。 ## 如何使用 上述所有内容都在 ssszcmawo/racoon2 (https://github.com/ssszcmawo/racoon2) 的 `gsoc2026` 分支上(已合并上游到 `zoulasc/racoon2`)。给想要试用的人一个快速导览: **构建与安装。** 仓库只提供 autotools 源码,因此必须先重新生成 configure 脚本——这也是 `doc/INSTALL` 中记录的流程,以及项目 CI 所采用的流程: ``` autoreconf -fi ./configure make make install ``` 你需要常规的开发者工具链(C 编译器、GNU make、autoconf、automake 和 libtool,以及 flex 和 bison)以及 OpenSSL 头文件;如果你想要 `kinkd` 守护进程,还需要一个 Kerberos 5 库(MIT krb5 或 Heimdal),而可选的数据包转储调试模式还需要 libpcap。 在 Debian/Ubuntu 上,CI 会在运行上述命令之前安装恰好这些包:`automake libtool libssl-dev libkrb5-dev libpcap-dev flex bison`。 有用的 configure 选项有:`--disable-iked`/`--disable-kinkd` 用来跳过某个守护进程,`--with-krb5=` 用于非标准的 Kerberos,`--enable-pcap` 用于数据包转储;`--prefix=$NEWDIR` 则可以把安装位置从默认的 `/usr/local` 移走。 **配置。** 所有需要的内容都在仓库的 `samples/` 下。`.in` 文件是模板,会在安装时填入其安装路径;场景片段则是普通文件。 对于 L2TP/IPsec 传输模式服务器——即本项目所针对的场景——流程如下: 1. 取 `samples/vals.conf.in` 作为你的 `vals.conf`,并在其中设置你的环境:`MY_IPADDRESS` 与 `PEERS_IPADDRESS`(如果事先不知道对端地址,则使用通配符 `IP_ANY`),如果你处于 NAT 之后还需要 `MY_PUBLIC_IPADDRESS`,以及共享密钥设置。密钥本身用 `pskgen` 生成。 2. 取 `samples/racoon2.conf.in` 作为你的 `racoon2.conf`。它 include 了 `vals.conf` 和 `default.conf` 并定义了接口;该样例中 NAT-T 是被注释掉的,附有说明: ``` interface { ike { MY_IP port 500; # MY_IP port 4500; # 取消注释以启用 NAT-T }; ... }; ``` 3. 为你想要的场景取消注释对应的那一行 `include`——这个例子中是 `transport_ike.conf`。该文件包含 `remote` 段(IKEv1 和 IKEv2,预共享密钥)、selector 和 policy: ``` selector ike_trans_sel_out { direction outbound; src "${MY_IPADDRESS}" port 1701; dst "${PEERS_IPADDRESS}" port any; upper_layer_protocol "udp"; policy_index ike_trans_policy; }; ... policy ike_trans_policy { action auto_ipsec; remote_index ike_trans_remote; ipsec_mode transport; ipsec_level require; ipsec_index { ipsec_esp; }; }; ``` 而如果你处于 NAT 之后,该文件自身被注释掉的一行 `include` 会拉入 `transport_ike_natt.conf`,其中带有针对常见私有地址段的额外 selector。 有两个细节值得注意:`vals.conf` 中的通配地址(`IP_ANY`)现在行为一致,因此服务器可以接受事先地址未知的对端;而且 IPv6 现在在相同的文件中即可使用——填入 IPv6 地址就会被采用,无需切换任何开关。 其他样例遵循相同的模式:隧道模式用 `tunnel_ike.conf` 和 `tunnel_ike_natt.conf`,基于 Kerberos 的密钥交换用 `transport_kink.conf` 和 `tunnel_kink.conf`,而在同一台机器上让两个守护进程互相对测则用 `local-test.conf`。 **运行它。** 先启动 `spmd`(它拥有到内核的策略通道),再用你的配置启动 `iked`——`./configure` 会把两者都就位,`samples/rc.d/` 中有面向 NetBSD 风格系统的 service 脚本。两者启动之后,匹配到某个 `action auto_ipsec` 的 selector(例如上面那个)的流量会自动触发协商,所以在客户端上你只需要使用内置的 Windows、iOS 或 Android VPN 客户端,填入服务器地址和共享密钥即可连接。 守护进程会记录 NAT 检测以及它所执行的替换操作,因此当某个客户端无法连上来时,很容易看清发生了什么。 **跟进这项工作。** 所有改动都在 `gsoc2026` 分支的 pull request #13–#39 中,`NEWS` 文件里有一条汇总条目描述了用户可见的变更。顶层的 `TODO` 文件列出了仍然开放的事项——参见下文的"遗留工作"一节。 ## 遇到的挑战 - **陈旧且无测试的代码。** racoon2 可以追溯到 WIDE 项目时代,没有任何测试。每次改动主要都得靠阅读代码、在调试器下手动运行守护进程、以及观察 sanitizers 来验证——这正是测试框架成为项目组成部分而非事后补充的原因。 - **RFC 合规性 vs. 能用的配置。** 实现地址替换意味着首先要理解响应方*为什么*需要那些仅对发起方有效的额外 selector,才能去除对它们的依赖;而让替换发生在 IKEv1 协商中正确的节点上,也尝试了好几次。 - **地址宏的深度远超表面。** 通配宏看起来像是一次简单的重命名,但在某些地方它们的含义是"该地址尚未知,内核策略必须等待",而在另一些地方则不然。在不破坏两种情况的前提下统一它们,需要仔细追踪配置解析、selector 匹配和策略更新的全过程。 - **构建系统的疏失。** 一个从别处引入、针对守护进程的可选构建补丁看似无害,却破坏了构建,最终不得不回退——这是一个很好的提醒:要真正把整个源码树构建起来,而不只是阅读 diff。 - **由 sanitizer 驱动的调试。** 用 sanitizers 构建暴露出在那些"多年都正常工作"的代码路径中的内存安全 bug;在不改变可观察行为的前提下修复它们,意味着要仔细跟踪每一个被复制的缓冲区的所有权归属。 ## 成果 - 所有工作已通过 pull request #13–#39 合并进 `gsoc2026` 分支的上游。 - `TODO` 清单上的每一项都已处理,除了 `racoon2ctl`:第二阶段 SA 管理(1)、IKEv1 的策略生成(3)、IPv6(4)、NAT-OA 载荷(5)、地址替换(6)、分片(7)以及地址宏的混乱(8)均已完成;只剩下第 2 项——优雅连接/断开的控制工具——仍处于开放状态。 - 一个自包含的单元测试框架,配有四个新的测试程序,覆盖 NAT-OA、地址替换和通配地址逻辑。完整的测试套件——包括原有的 crypto 自检——在 sanitizers 下干净地通过:5 个测试程序中 5 个通过,0 个失败。 - 一条新的 `NEWS` 条目,以及与新默认值一致的文档和示例配置。 ## 遗留工作 以下事项记录在顶层的 `TODO` 文件中,是有意留给未来工作的: - **一个 `racoon2ctl` 工具。** 发起方仍然没有办法优雅地连接和断开:向守护进程发送 SIGTERM 并不会像 IKEv2 连接那样删除安全关联或向对端发送删除通知,而对于 IKEv1 来说这一差距尤其明显。一个小的控制工具(以及它背后的"关机时删除"行为)会让 racoon2 的行为像一个正规的长期运行服务,而不是一个被人杀掉又重新启动的东西。 - **为仍然没有测试的功能编写测试。** 本项目只为自己引入的逻辑添加了测试。守护进程的其余部分——第二阶段 SA 生命周期、策略生成、重新密钥协商(rekeying)、分片路径、整个配置解析器——仍然只能通过手动运行来验证。为这些区域扩展测试框架是顺理成章的下一步,这里添加的与 purge 相关的测试正是为此打下的起点。 - **端到端的 IPv6 测试。** IPv6 在配置侧现在可以工作了,但仍需要在 NetBSD 和 Linux 的真实场景中进行更为彻底的测试:完整的 IPv6 隧道、与 NAT-T 的交互、以及发起方和响应方两侧的长期连接,都还没有被实际验证过。 ## 结论 本项目起初是"逐项清理 TODO 清单",但最终成长为一个稳健性大幅提升的 racoon2:NAT 穿越现在对两个 IKE 版本都遵循相关 RFC,IPv6 确实可用并默认启用,配置行为一致,而且——也许对长期来说最重要的是——守护进程终于拥有了一套在 sanitizers 下运行的自动化测试套件。开放的事项集中收集在上文的"遗留工作"一节。我相信,RFC 级别的修复与回归测试框架的结合……

相似文章

NetBSD GSoC 2026 改进 RAIDframe

Hacker News Top

这篇文章报道了Google Summer of Code 2026年在NetBSD中改进RAIDframe的工作,包括实现用于多磁盘镜像的N-way RAID 1和添加RAID scrubbing支持。

基于 NetBSD 的研究

Hacker News Top

本 NetBSD 画廊页面重点展示了各类基于该操作系统的学术及工业研究项目,包括 NASA 的卫星 TCP 实验、KAME IPv6/IPsec 项目以及高速网络演示。

NetBSD GSoC 2026:测试兼容性 Linux 系统调用

Lobsters Hottest

一份 Google Summer of Code 2026 项目报告详细介绍了使用 Linux Test Project 改进 NetBSD 的 Linux 兼容层测试的努力,包括编译测试、创建包和记录系统调用模拟。

实验性 OpenBSD MAP-E CE 支持(反馈)

Lobsters Hottest

该项目提供补丁和脚本,用于向 OpenBSD 7.8 路由器添加实验性 MAP-E CE(RFC7597)支持,包括内核补丁和一个名为 maped 的配套应用程序。

死而未僵的软件:relayd(8) 与 httpd(8) 的持续演进

Lobsters Hottest

一篇博客文章,详细介绍了 OpenBSD 的 relayd(8) 和 httpd(8) 守护进程正在进行的复兴与现代化,包括使 imsg 消息系统现代化以及处理待定补丁的努力,作者称 LLM 是促使自己回归 C 语言编程的动因。