Socket_Kernel_Module 08

4.3 Netfilter总体结构

4.3.1 介绍

Netfilter是嵌入内核IP协议栈的一系列调用入口,设置在报文处理的路径上。网络报文按照来源和去向,可以分为三类:流入的、流经的和流出的,其中流入和流经的报文需要经过路由才能区分,而流经和流出的报文则需要经过投递,此外,流经的报文还有一个FORWARD的过程,即从一个NIC转到另一个NIC。Netfilter就是根据网络报文的流向,在以下几个点插入处理过程:

NF_IP_PRE_ROUTING,在报文作路由以前执行;

NF_IP_FORWARD,在报文转向另一个NIC以前执行;

NF_IP_POST_ROUTING,在报文流出以前执行;

NF_IP_LOCAL_IN,在流入本地的报文作路由以后执行;

NF_IP_LOCAL_OUT,在本地报文做流出路由前执行。

 

Netfilter框架为多种协议提供了一套类似的钩子(HOOK),用一个struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS]二维数组结构存储,一维为协议族,二维为上面提到的各个调用入口。每个希望嵌入Netfilter中的模块都可以为多个协议族的多个调用点注册多个钩子函数(HOOK),这些钩子函数将形成一条函数指针链,每次协议栈代码执行到NF_HOOK()函数时(有多个时机),都会依次启动所有这些函数,处理参数所指定的协议栈内容。

每个注册的钩子函数经过处理后都将返回下列值之一,告知Netfilter核心代码处理结果,以便对报文采取相应的动作:

NF_ACCEPT:继续正常的报文处理;

NF_DROP:将报文丢弃;

NF_STOLEN:由钩子函数处理了该报文,不要再继续传送;

NF_QUEUE:将报文入队,通常交由用户程序处理;

NF_REPEAT:再次调用该钩子函数。

 

4.3.2 注册和注销Netfilter hook

4.3.2.1 nf_hook_ops数据结构

注册一个hook函数是围绕nf_hook_ops数据结构的一个非常简单的操作,nf_hook_ops数据结构在linux/netfilter.h中定义,该数据结构的定义如下:

struct nf_hook_ops {
         struct list_head list; //内核通用链表

         nf_hookfn *hook;   //该函数是这个hook被调用时执行的函数,间后

         int pf;              用于指定协议族, 对IPv4使用协议族PF_INET
         int hooknum;  //指定安装的这个函数对应的具体的hook类型,前面NF_IP_***
         int priority;    // Hook的优先级,见后
};

对参数的说明

(1)

typedef unsigned int nf_hookfn(unsigned int hooknum,  //指定安装的这个函数对应的具体的hook类型,前面NF_IP_***
                                 struct sk_buff **skb, //网络堆栈用sk_buff数据结构来描述数据包,
                                 const struct net_device *in,  //描述数据包到达的接口
                                 const struct net_device *out,    //描述数据包离开的接口
                                 int (*okfn)(struct sk_buff *)); //尚待研究,?

 

a.其中sk_buff是很重要的数据结构,包括很多内容,其中最重要的就是三个描述传输层包头(例如:UDP, TCP, ICMP, SPX)、网络层包头(例如:IPv4/6, IPX, RAW)以及链路层包头(例如:以太网或者RAW), 网络不同层的封装、组合几乎都是对这几个包头的处理。

 

b. net_device数据结构被Linux内核用于描述所有类型的网络接口。这两个参数中的第一个——in,用于描述数据包到达的接口,毫无疑问,参数out用于描述数据包离开的接口。必须明白,在通常情况下,这两个参数中将只有一个被提供。例如:参数in只用于NF_IP_PRE_ROUTING和NF_IP_LOCAL_IN hook,参数out只用于NF_IP_LOCAL_OUT和NF_IP_POST_ROUTING hook

 

c.

 

 

(2)

hook优先级,这里考虑ipv4即可

enum nf_ip_hook_priorities {
          NF_IP_PRI_FIRST = INT_MIN,
          NF_IP_PRI_CONNTRACK_DEFRAG = -400,
          NF_IP_PRI_RAW = -300,
          NF_IP_PRI_SELINUX_FIRST = -225,
          NF_IP_PRI_CONNTRACK = -200,
          NF_IP_PRI_MANGLE = -150,
          NF_IP_PRI_NAT_DST = -100,
          NF_IP_PRI_FILTER = 0,
          NF_IP_PRI_NAT_SRC = 100,
          NF_IP_PRI_SELINUX_LAST = 225,
          NF_IP_PRI_CONNTRACK_HELPER = INT_MAX - 2,
          NF_IP_PRI_NAT_SEQ_ADJUST = INT_MAX - 1,
          NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
          NF_IP_PRI_LAST = INT_MAX,
  }; 

 

4.3.2.2 nf_register_hook注册和nf_unregister_hook注销

参考源代码,可以看到nf_register_hook其实就是注册到struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS]中(参考上文),

int nf_register_hook(struct nf_hook_ops *reg)
{
    struct list_head *i;

    br_write_lock_bh(BR_NETPROTO_LOCK);
    for (i = nf_hooks[reg->;pf][reg->;hooknum].next;
         i != &nf_hooks[reg->;pf][reg->;hooknum];
         i = i->;next) {
        if (reg->;priority < ((struct nf_hook_ops *)i)->;priority)
            break;
    }
    list_add(&->;list, i->;prev);
    br_write_unlock_bh(BR_NETPROTO_LOCK);
    return 0;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值