【问题标题】:netfilter-like kernel module to get source and destination address类似于 netfilter 的内核模块,用于获取源地址和目标地址
【发布时间】:2015-04-16 09:44:37
【问题描述】:

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

首先,我不知道下面的文字是什么意思,入站和出站数据包有什么区别(按传输层)?

当一个数据包从线路进入时,它从物理层传输,数据 链路层,网络层向上,因此它可能不会通过 netfilter 中为 skb_transport_header 工作定义的函数。

其次,我讨厌幻数,我想用 linux 内核实用程序中的任何函数 (source file) 替换 20(典型 IP 标头的长度)。

任何帮助将不胜感激。

【问题讨论】:

    标签: linux linux-kernel kernel-module


    【解决方案1】:

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

    对于新内核 (>= 3.11)

    如果您确定您的代码只能用于 >= 3.11 的内核,您可以将下一个代码用于 inputoutput 数据包:

    udp_header = (struct udphdr *)skb_transport_header(skb);  
    

    或者更优雅:

    udp_header = udp_hdr(skb);
    

    因为ip_rcv()中已经为你设置好了transport header

    skb->transport_header = skb->network_header + iph->ihl*4;
    

    这个改动是由this commit带来的。

    对于旧内核 (

    传出数据包 (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 标头(即网络层标头)。

    所以你需要自己计算transport header的地址。为此,您需要跳过 IP 标头(即将 IP 标头长度添加到您的.transport_header 地址)。这就是为什么您可以在文章中看到下一个代码:

    udp_header = (struct udphdr *)(skb_transport_header(skb) + 20);
    

    所以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

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

    if (ip_header->protocol == 17) {
    

    在此代码中,您应该使用IPPROTO_UDP 而不是17

    #include <linux/udp.h>
    
    if (ip_header->protocol == IPPROTO_UDP) {
    

    Netfilter输入/输出包说明

    如果您需要一些关于 netfilter 中传入和传出数据包的区别的参考,请参见下图。

    详情:

    [1]:Some useful code from GitHub

    [2]:"Linux Kernel Networking: Implementation and Theory" by Rami Rosen

    [3]:This answer may be also useful

    【讨论】:

    • 感谢您的详细解答!
    • 另外感谢您指出 17 作为 IPPROTO_UDP,我在发布答案之前已经挖掘出来了。
    猜你喜欢
    • 2021-06-21
    • 2012-05-28
    • 2011-09-09
    • 2016-08-23
    • 2019-08-19
    • 2016-05-16
    • 2012-02-01
    • 2013-03-10
    • 2020-07-01
    相关资源
    最近更新 更多