Linux kernel 如何自然地翻译Linux内核中的第3层头文件?

Linux kernel 如何自然地翻译Linux内核中的第3层头文件?,linux-kernel,netfilter,Linux Kernel,Netfilter,我的任务是为Linux内核编写一个IPv4-IPv6转换器()。简而言之,它是一个网关,位于IPv4和IPv6网络之间,通过交换数据包头和屏蔽地址,允许它们之间进行透明通信 看到内核有Netfilter,一个用于修改数据包的框架,最初我认为我可以编写一个Netfilter模块并从中进行翻译。我可以截获所有数据包,使用通常的skb_pull/skb_push操作调整它们的大小,覆盖一些字节,最后愉快地将它们返回内核 事实证明,交换协议对于Netfilter来说太极端了。因为处理IPv4数据包的代码

我的任务是为Linux内核编写一个IPv4-IPv6转换器()。简而言之,它是一个网关,位于IPv4和IPv6网络之间,通过交换数据包头和屏蔽地址,允许它们之间进行透明通信

看到内核有Netfilter,一个用于修改数据包的框架,最初我认为我可以编写一个Netfilter模块并从中进行翻译。我可以截获所有数据包,使用通常的skb_pull/skb_push操作调整它们的大小,覆盖一些字节,最后愉快地将它们返回内核

事实证明,交换协议对于Netfilter来说太极端了。因为处理IPv4数据包的代码与处理IPv6数据包的代码完全独立,所以Netfilter模块的先前和后续代码都假定网络协议的头仍然存在。因此,如果我将IPv4报头更改为IPv6报头,内核将发疯,因为它将继续读取报头,就像它是IPv4报头一样

(或者至少,在阅读net/ipv4/ip_input.c之后,我相信这一点;在调用NF_HOOK之后,内核要做的第一件事是在ip_rcv_finish()期间提取ipv4报头。)

我看到了第二种选择:从头推导一个新的sku buff,让Netfilter删除原始数据包,然后以某种方式发送新数据包

这就是我对内核原理和风格的有限熟悉让我停滞不前的地方:我想尽量减少对我的解决方案的不满,但替换整个数据包而不是修改其标题似乎是不自然的、不完善的,甚至是对Netfilter设计的亵渎。但我不能确定,我想听听有经验的建议。此外,我看不到其他选择

问题:还有其他选择吗?最自然的方法是什么


我想支持自2.6以来的所有内核版本。如果这是不可能的,更新的更好。

我曾经写过一个ebtables目标,任务是用VLAN标记以太网帧。这需要在帧数据之前移动和更改以太网报头。所以它也在做类似的事情,但是在较低的层次上。skb可以在一开始就放大(我想至少在大多数情况下是这样),所以性能应该可以

直接链接:

它是“008-ebt-vlan_t-0.1.diff.bz2”,位于:


请注意,我已经有4年多没有关注过这段代码了,从那时起我就不再使用Linux网络代码了。与此同时,Ebtables已合并到netfilter中,AFAIK。但是我认为基本方法应该仍然有效,并且可以帮助您。

我不知道如何避免替换整个数据包,因为您正在交换不同的网络头。您必须将新数据包重新注入堆栈中,并且它应该具有适当的数据链路头(例如以太网)。NAT64无论如何都是一个愚蠢的黑客;通过某种方式提高效率,你实际上是在打磨一个垃圾。先让它工作吧。我可能会把话塞进你的嘴里;让我看看我是否明白了这一点:通过使用ebtables(第2层)而不是iptables(第3层+),我将在帧到达内核的网络层之前更改网络头。因此,从一开始就不需要更换管道。担忧:站在第二层,我将不会被conntrack等功能所屏蔽(因为它发生在后面),所以我必须自己组装碎片。其他基本的验证也浮现在脑海中;我需要重新实现很多东西。我错了吗?@YdAhhrk:你不必把ebtables当作任何新东西来使用。实际上,ebtables和iptables在某个时候被合并到xtables中,并且在netfilter中以相同的方式工作(请参见
find net/netfilter | grep xt
)。我相信这种转换在netfilter挂钩的任何位置都会起作用。每个
skb
在skb数据之前和之后都分配了一些空间,以防Linux需要预先添加/附加更多内容。我认为我们有点不同步了:/。添加头相对容易,因为它不会太多地干扰内核的基本假设(例如,sku buff中指向有效数据链接和网络头的指针)。但事实证明,将IPv4报头转换为IPv6报头被认为是“太多事了”,这是我的问题。我现在意识到我的问题可能会更有条理。很抱歉,将在一分钟内进行编辑。@YdAhhrk:在这种情况下,我很确定您可以“使用”skb,修改它,然后将其注入netfilter以再次处理。但是处理数据包的代码必须通过skb中的一些数据知道它是什么协议,并且您可能需要修改更多的内容,而不仅仅是原始的skb数据。仔细调试并理解哪里出了问题,哪里应该有所帮助。那么,再次投票支持重新注入。我将把这个问题再留待一周;如果它不能吸引更多的意见,我会接受这个答案。