我阅读本指南编写一个内核模块来做简单的networking过滤。
首先,我不知道下面的文本是什么意思,入站和出站数据包(通过传输层)有什么区别?
当数据包从有线networking进入时,它从物理层,数据链路层,networking层向上传播,因此可能不会通过netfilter中为skb_transport_header定义的function工作。
其次,我讨厌魔术数字,我想用Linux内核的实用程序( 源文件 )中的任何函数replace20 (典型的IP头文件的长度)。
劫持__NR_read和bash崩溃(caf用户?)
Android和内核模块
如何写一个正在写入特定设备的杯栅格驱动程序
发送SKB从内核空间传输
任何帮助将不胜感激。
实际上在文件描述符中存储了多less信息?
“无法在虚拟地址处理内核NULL指针解引用”。 – 在发出内核模块信号时 OOPS
编写多functioni2c设备的内核模块 – 一个或多个?
如何在内核中使用性能计数器?
这篇文章现在有点过时了。 您不理解的文本仅适用于3.11以下的内核版本。
对于新内核(> = 3.11)
如果您确定您的代码只用于内核> = 3.11,则可以使用下一个代码来处理输入和输出数据包:
udp_header = (struct udphdr *)skb_transport_header(skb);
或者更优雅:
udp_header = udp_hdr(skb);
这是因为传输头已经在ip_rcv()中为你设置了:
skb->transport_header = skb->network_header + iph->ihl*4;
这个改变是由这个提交带来的。
对于旧的内核(<3.11)
传出数据包( NF_INET_POST_ROUTING )
在这种情况下.transport_header字段在sk_buffer正确设置,所以它指向实际的传输层头(UDP / TCP)。 所以你可以使用这样的代码:
udp_header = (struct udphdr *)skb_transport_header(skb);
或更好看(但实际上是相同的):
udp_header = udp_hdr(skb);
入站数据包( NF_INET_PRE_ROUTING )
这是棘手的部分。
在这种情况下, .transport_header字段没有设置为sk_buffer结构中的实际传输层头(UDP或TCP)(在netfilter钩子函数中)。 而.transport_header指向IP标头(这是网络层标头)。
所以你需要自己计算传输头的地址。 为此,您需要跳过IP标头(即将IP标头长度添加到您的.transport_header地址)。 这就是为什么你可以看到文章中的下一个代码:
udp_header = (struct udphdr *)(skb_transport_header(skb) + 20);
所以这里只是IP头的长度。
这样做可以做得更高雅:
struct iphdr *iph; struct udphdr *udph; iph = ip_hdr(skb); /* If transport header is not set for this kernel version */ if (skb_transport_header(skb) == (unsigned char *)iph) udph = (unsigned char *)iph + (iph->ihl * 4); /* skip IP header */ else udph = udp_hdr(skb);
在这个代码中,我们使用了一个实际的IP头大小(这是iph->ihl * 4 ,以字节为单位),而不是20的幻数。
if (ip_header->protocol == 17) {
#include <linux/udp.h> if (ip_header->protocol == IPPROTO_UDP) {
Netfilter输入/输出包的解释
如果您需要关于netfilter中传入和传出数据包之间差异的一些参考信息,请参见下图。
细节:
[1]: 来自GitHub的一些有用的代码
[2]: Rami Rosen的“Linux coreel Networking:Implementation and Theory”
[3]: 这个答案可能也有用
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。