我正在尝试解决 ESP 数据包碎片化的问题,因为在添加 ESP 标头后超出了 MTU 大小。解决方案(每个人都这样做)是在进行 ESP 加密之前进行分段。
我的问题是,如果这很有用,为什么 Linux IPSec 实现本身不支持它。我了解 L4 流量选择器无法工作的某些限制。但并不是每个人都使用它。
此外,如果您可以分享有关添加此支持的最佳方式的任何指示,那将真的很有帮助。
谢谢。
我正在尝试解决 ESP 数据包碎片化的问题,因为在添加 ESP 标头后超出了 MTU 大小。解决方案(每个人都这样做)是在进行 ESP 加密之前进行分段。
我的问题是,如果这很有用,为什么 Linux IPSec 实现本身不支持它。我了解 L4 流量选择器无法工作的某些限制。但并不是每个人都使用它。
此外,如果您可以分享有关添加此支持的最佳方式的任何指示,那将真的很有帮助。
谢谢。
为了完成这个循环(并希望帮助可能正在寻找类似解决方案的人),我们通过使用libnetfilter_queue解决了我们的问题。我们面临的挑战是,我们无法访问应用程序的源代码,否则我们可以在应用程序级别本身完成碎片。
这是我们内部文件的相关摘录,由Sriram Dharwadkar编写,他也进行了实施。其中一些引用是我们内部应用程序的名称,但不要认为您在理解上有任何问题。
NetFilter Queues是用户空间库,它提供 API 来处理内核数据包过滤器排队的数据包。愿意使用此功能的应用程序应动态链接到netfilter_queue和nfnetlink,并包括来自 sysroot-target/usr/include/libnetfilter_queue/ 和 sysroot-target/usr/include/libnfnetlink/ 的必要标头。需要添加以NFQUEUE为目标的iptables。NFQUEUE 是一个 iptables 和 ip6tables 目标,它将对数据包的决定委托给用户空间软件。例如,下面的规则将要求一个监听用户空间程序对所有排队的数据包做出决定。
iptables -A INPUT -j NFQUEUE --queue-num 0
在用户空间中,软件必须使用 libnetfilter_queue api 连接到队列 0(默认队列)并从内核获取消息。然后它必须对数据包作出裁决。
当一个数据包到达一个 NFQUEUE 目标时,它被排入与 --queue-num 选项给出的数字相对应的队列中。数据包队列被实现为链表,其中元素是数据包和元数据(Linux 内核 skb):
Prefragmentation 逻辑在 AvPreFragApp(新应用程序)和 Security Broker(现有控制器应用程序)中实现。
在安全代理中,一旦建立隧道。将以下两条规则添加到 RAW 表中。
对于 TCP 预分片:
/usr/sbin/iptables -t raw -I OUTPUT 1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1360
以上规则在三向握手期间协商适当的 MSS 大小。可以安全地假设,1360+TCPH+IPH+ESP+IPH <= 1500,因此加密后不会发生碎片。
对于 UDP 预分片:
/usr/sbin/iptables -t raw -I OUTPUT 2 -s <tia> -p udp -m mark !--mark 0xbeef0000/0xffff0000 -j NFQUEUE
上述规则将所有 src ip 为 TIA(隧道地址)的 udp 数据包排队,并将不等于 0xbeef0000 标记到 netfilter 队列以供应用程序处理。AvPreFragApp 将在所有排队的 udp 数据包上标记 0xbeef0000。这样做是为了避免数据包的重复排队。
AvPreFragApp 应用程序使用 netfilter 队列来处理由 NFQUEUE 目标排队的数据包。如上所述,将具有 TIA 作为 src ip 的 udp 数据包排队的 iptables 规则已添加到安全代理中。此规则在隧道建立时添加,并在使用新 TIA 的隧道反弹时更新。因此,所有以 TIA 为源 ip 的数据包都排队等待 AvPreFragApp 处理。
注意:TIA:隧道内部地址,逻辑 IPSec 接口。