netfilter框架分析

本来是不打算写这种基础性的东西的,但是有很多同志经常问我(有同事也有网友)。所以就写一下吧,这个是理解LINUX内核网络子系统的基础,ip conntrack等都是依赖这些基础的。好的,闲话不多说了。来正文。

其实netfilter就是依靠一个全局的二维数组nf_hooks[][].可以把这个玩意看成一个8*32的矩阵。矩阵的每个成员就是一个双向链表节点。看看,又是双向链表,内核中双向链表的地位真的太重要了。以双向链表做骨架串起nf_hook_ops这个结构体。然后在运行时在挂HOOK的地方调用nf_iterate这个函数(叫的高深一点就叫迭代器,面试的时候我喜欢叫迭代器装B吓唬人^_^)依次从链表上取下nf_hook_ops中注册的函数并执行。下面先给出一个图。

netfilter框架分析

然后HOOKS分别挂在五个地方,这五个地方分别对应着nf_hooks[NPROTO][NF_MAX_HOOKS]中NF_MAX_HOOKS的成员。

在内核中用宏来实现的(其实用一个枚举来实现会更优雅一些):

/* IP Hooks */
/* After promisc drops, checksum checks. */
#define NF_IP_PRE_ROUTING0
/* If the packet is destined for this box. */
#define NF_IP_LOCAL_IN1
/* If the packet is destined for another interface. */
#define NF_IP_FORWARD2
/* Packets coming from a local process. */
#define NF_IP_LOCAL_OUT3
/* Packets about to hit the wire. */
#define NF_IP_POST_ROUTING4
#define NF_IP_NUMHOOKS5

这就是整个netfilter的基础骨架,所有IP包都是经过这五个钩子来处理的。

下面给出整体的框图:

netfilter框架分析

接下来最后一个细节了:

那就是nf_hook_ops函数返回值的潜规则:

#define NF_DROP 0
#define NF_ACCEPT 1
#define NF_STOLEN 2
#define NF_QUEUE 3
#define NF_REPEAT 4
#define NF_STOP 5
#define NF_MAX_VERDICT NF_STOP

netfilter框架就认这几个返回值了。如果不按照规矩来的话,出了问题就别怪人家了。就像你去商店买东西一样,你如果拿人民币出来,人家愿意接受,你拿美元,如果老板是个行家也会接受,你如果拿冥钞的话,老板会发火的,所以你首先要摸清楚老板的脾气,不要拿冥钞,这个道理是很浅显的,所以同样,按照人家的规矩来给返回值也是很浅显的,照做就行了。

下面介绍一下这几个返回值的意思:

NF_DROP 就是把这个包扔掉,不要了,对应的SKB也会被释放。

NF_ACCEPT 这个包是我想要的,留下,继续往下跑。

NF_STOLEN 不做任何处理,SKB也不会释放,所以同志们要注意了,如果自已要玩高级点的一定要摸清楚再玩,半生不熟的就玩的话很容易出问题的。

NF_QUEUE 扔进SKB的队列里面,接下来就是往用户空间扔啦。

NF_STOP 这个和NF_ACCEPT的意义是一致的,但有一点区别,NF_ACCEPT接收到包后会继续往后面扔,就是会往下一个HOOK点扔,但NF_STOP就不会继续跑后面的HOOK点了。

就这么多了。很简单吧。