实现RFC5858时注册自定义XFRM类型遇内核限制,求解决方案
我正在实现RFC5858,该标准提出了一种对IPsec ESP报文载荷内的headers头部进行压缩的方案。原本计划开发Linux内核模块,但受限于Linux内核代码中的协议号限制(内核xfrm_state.c中的相关校验逻辑),计划无法推进。我使用的自定义协议号为142(ESP用50,IPcomp用106),调用xfrm_register_type注册自定义XFRM类型时失败,请问该如何解决?制作“raw”补丁是否符合行业常规?
示例代码
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> #include <net/ip.h> #include <net/xfrm.h> #define MY_CUSTOM_PROTOCOL 142 static const struct xfrm_type my_custom_xfrm_type = { .owner = THIS_MODULE, .proto = MY_CUSTOM_PROTOCOL, }; static int __init my_custom_module_init(void) { int err = xfrm_register_type(&my_custom_xfrm_type, AF_INET); if(err < 0) { printk(KERN_INFO "Can't add type"); } else { printk(KERN_INFO "Added type"); } return err; } static void __exit my_custom_module_exit(void) { xfrm_unregister_type(&my_custom_xfrm_type, AF_INET); } module_init(my_custom_module_init); module_exit(my_custom_module_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("Custom XFRM Module");
插入模块时的错误输出
insmod: ERROR: could not insert module ./custom_type.ko: Protocol not supported
1. 注册失败的核心原因
内核xfrm_register_type函数会校验协议号是否属于预定义的允许范围(如ESP、AH、IPcomp等),自定义协议号不在白名单内,因此直接通过模块注册会被拒绝。
2. 可行的解决途径
途径一:修改内核源码添加协议号白名单
直接修改xfrm_state.c中限制协议号的代码,将142号协议加入允许列表,重新编译内核即可让模块正常注册。操作要点是找到内核中校验协议号的逻辑位置,添加对应协议号的判断分支或放宽校验条件。途径二:复用现有XFRM扩展机制
不需要新增协议号,复用IPcomp(协议号106)的扩展框架,将你的压缩逻辑作为IPcomp的新算法实现。这种方式兼容现有内核的XFRM体系,无需修改核心校验逻辑。途径三:使用Netfilter钩子绕过XFRM注册
通过Netfilter的NF_INET_PRE_ROUTING和NF_INET_POST_ROUTING钩子,直接在IP层处理ESP载荷的压缩/解压缩逻辑,完全绕开XFRM的协议号限制。该方式灵活性高,但需要自行处理报文封装、状态管理等逻辑,开发工作量更大。
3. 关于“raw”补丁的行业常规
制作针对内核源码的“raw”补丁(直接修改内核核心代码)在研究、实验或特定场景部署中是常见操作,但不适合通用生产环境:
- 优势:实现简单,能快速验证RFC方案的可行性。
- 劣势:补丁需要随内核版本更新维护,无法兼容未打补丁的内核,难以推广到通用系统。
- 长期建议:如果希望方案被上游内核接纳,需遵循Linux内核社区规范提交补丁——先通过邮件列表发起讨论,说明RFC5858的技术价值,争取将142号协议加入官方白名单,或把压缩逻辑整合到现有IPsec框架中。
内容的提问来源于stack exchange,提问作者Quentin Baradat

