Linux 类似netfilter的内核模块,用于获取源地址和目标地址

Linux 类似netfilter的内核模块,用于获取源地址和目标地址,linux,linux-kernel,kernel-module,Linux,Linux Kernel,Kernel Module,我读写了一个内核模块来做简单的网络过滤 首先,我不知道下面的文字是什么意思,按传输层划分的入站数据包和出站数据包之间的区别是什么 当数据包从导线进入时,它从物理层(数据层)开始传输 链路层、网络层向上,因此可能无法通过 netfilter中为skb_transport_标头定义的函数可以工作 其次,我讨厌神奇的数字,我想用linux内核实用程序中的任何函数替换典型IP头长度的20 任何帮助都将不胜感激。这篇文章现在有点过时了。您不理解的文本仅适用于3.11以下的内核版本 对于新内核>=3.11

我读写了一个内核模块来做简单的网络过滤

首先,我不知道下面的文字是什么意思,按传输层划分的入站数据包和出站数据包之间的区别是什么

当数据包从导线进入时,它从物理层(数据层)开始传输 链路层、网络层向上,因此可能无法通过 netfilter中为skb_transport_标头定义的函数可以工作

其次,我讨厌神奇的数字,我想用linux内核实用程序中的任何函数替换典型IP头长度的20


任何帮助都将不胜感激。

这篇文章现在有点过时了。您不理解的文本仅适用于3.11以下的内核版本

对于新内核>=3.11 如果您确定您的代码将仅用于内核>=3.11,则可以对输入和输出数据包使用下一个代码:

udp_header=struct udphdr*skb_transport_headerskb; 或者更优雅:

udp_头=udp_hdrskb; 这是因为已在中为您设置了传输标头:

skb->transport_header=skb->network_header+iph->ihl*4; 这一变化是由美国带来的

对于小于3.11的旧内核 传出数据包NF_INET_POST_路由 在本例中,在sk_缓冲区中正确设置了.transport_头字段,因此它指向实际的传输层头UDP/TCP。因此,您可以使用如下代码:

udp_header=struct udphdr*skb_transport_headerskb; 或者看起来更好,但实际上是一样的:

udp_头=udp_hdrskb; 传入数据包NF_INET_PRE_路由 这是棘手的部分

在这种情况下,.transport_头字段未设置为在netfilter钩子函数中获得的sk_缓冲区结构中的实际传输层头UDP或TCP。相反,.transport_头指向IP头,它是网络层头

所以您需要自己计算传输头的地址。为此,您需要跳过IP头,即将IP头长度添加到.transport\u头地址。这就是为什么您可以在本文中看到下一个代码:

udp_头=结构udphdr*skb_传输_头KB+20; 这里是IP头的长度

可以通过以下方式使其更加优雅:

结构iphdr*iph; 结构udphdr*udph; iph=ip_hdrskb; /*如果未为此内核版本设置传输标头*/ 如果skb_传输_标头KB==未签名字符*iph udph=无符号字符*iph+iph->ihl*4;/*跳过IP头*/ 其他的 udph=udp_hdrskb; 在这段代码中,我们使用实际的IP头大小,即iph->ihl*4,以字节为单位,而不是幻数20

文章中的另一个神奇数字是下一个代码中的17:

如果ip_头->协议==17{ 在此代码中,您应该使用IPPROTO_UDP而不是17:

包括 如果ip_头->协议==IPPROTO_UDP{ Netfilter输入/输出数据包说明 如果您需要了解netfilter中传入和传出数据包之间的差异,请参见下图

详情:

[1] :

[2] :


[3] :

这篇文章现在有点过时了。您不理解的文本只适用于3.11以下的内核版本

对于新内核>=3.11 如果您确定您的代码将仅用于内核>=3.11,则可以对输入和输出数据包使用下一个代码:

udp_header=struct udphdr*skb_transport_headerskb; 或者更优雅:

udp_头=udp_hdrskb; 这是因为已在中为您设置了传输标头:

skb->transport_header=skb->network_header+iph->ihl*4; 这一变化是由美国带来的

对于小于3.11的旧内核 传出数据包NF_INET_POST_路由 在本例中,在sk_缓冲区中正确设置了.transport_头字段,因此它指向实际的传输层头UDP/TCP。因此,您可以使用如下代码:

udp_header=struct udphdr*skb_transport_headerskb; 或者看起来更好,但实际上是一样的:

udp_头=udp_hdrskb; 传入数据包NF_INET_PRE_路由 这是棘手的部分

在这种情况下,.transport_header字段未设置为在netfilter钩子函数中获得的sk_缓冲区结构中的实际传输层头UDP或TCP。相反,.transport_头指向作为网络层头的IP头

因此,您需要自己计算传输头的地址。为此,您需要跳过IP头,即将IP头长度添加到.transport\u头地址。这就是为什么您可以在本文中看到下一个代码:

udp_头=结构udphdr*skb_传输_头KB+20; 这里是IP头的长度

可以通过以下方式使其更加优雅:

结构iphdr*iph; 结构udphdr*udph; iph=ip_hdrskb; /*如果未为此内核版本设置传输标头*/ 如果skb_传输_标头KB==未签名字符*iph udph=无符号字符*iph+iph->ihl*4;/*跳过IP头*/ 其他的 udph=udp_hdrskb; 在这段代码中,我们使用实际值 l IP头大小,即iph->ihl*4,以字节为单位,而不是幻数20

文章中的另一个神奇数字是下一个代码中的17:

如果ip_头->协议==17{ 在此代码中,您应该使用IPPROTO_UDP而不是17:

包括 如果ip_头->协议==IPPROTO_UDP{ Netfilter输入/输出数据包说明 如果您需要了解netfilter中传入和传出数据包之间的差异,请参见下图

详情:

[1] :

[2] :


[3] :

谢谢你的详细回答!也谢谢你指出17为IPPROTO_UDP,我在发布答案之前已经挖掘出来了。谢谢你的详细回答!也谢谢你指出17为IPPROTO_UDP,我在发布答案之前已经挖掘出来了。