分类: LINUX
2013-03-06 22:51:20
要想理解Netfilter的工作原理,必须从对Linux IP报文处理流程的分析开始,Netfilter正是将自己紧密地构建在这一流程之中的。IP 协议栈是Linux操作系统的主要组成部分,也是Linux的特色之一,素以高效稳定著称。Netfilter与IP协议栈是密切结合在一起的,我们以接收报文为例,简要介绍一下IPv4协议栈(IP层)的报文处理过程。
报文接收从网卡驱动程序开始,当网卡收到一个报文时,会产生一个中断,其驱动程序中的中断服务程序将调用确定的接收函数来处理。流程分成两个阶段:驱动程序中断服务程序阶段和IP协议栈处理阶段,驱动程序的处理流程与本章的联系不是十分紧密,故不做详细的介绍,我们以下面的流程图简要介绍以下数据包的接收过程。
驱动程序处理报文时,会生成一个skb_buff,同时将其放入一个全局的存储结构当中,同时设置软中断NET_RX_SOFTIRQ等待内核处理,内核收到软中断后,报文便开始了协议栈之旅。我们用以下的流程图来表示接收报文时整个处理的流程:
从图3.1的流程可以看出,Netfilter以NF_HOOK形式挂载到ip协议栈对报文的处理过程中,然后将相应的数据包转入到Netfilter中来处理,我们可以将IP协议栈中调用NF_HOOK的地方称之为挂载点。除了流程图中指出的几处挂载点,Netfitler还在ip协议栈的多处进行了挂载,可以具体参考内核网络部分的源码。
Netfilter的扩展通过对全局变量的注册来完成。所谓的注册其本质上就是将数据存储到全局变量中,为后续的调用做好准备,Netfilter的注册机制可以分为表注册,target注册,match注册,hook操作注册。
表注册就是将定义好的表存放到一个全局变量xt的tables成员变量中,这个成员变量为一个xt_af的结构体,定义如下:
*
*这是一个存放所有规则信息及表信息的数据结构
*/
struct xt_af {
struct mutex
mutex;
struct
list_head match;//所有在内核中注册的match信息
struct
list_head target;//所有在内核中注册的target信息
struct
list_head tables;//所有表的信息
struct mutex
compat_mutex;
};
static struct xt_af
*xt;//一个全局变量,存储了所有内核和用户空间需要的规则信息。
与表注册类似,target注册和match注册也是通过向全局变量xt的成员变量写入信息来完成的。Netfilter通过这种注册的方式来实现对其扩展机制,用户可以根据自己的需求来实现match,target,甚至是自己实现一个表,然后注册到相应的全局变量,当数据包进入Netfilter后,hook操作会查找对应的表,以实现对数据包的匹配和处理。
Hook操作的注册的地点与上面三个注册不同。先来看下什么是hook操作。Netfilter在不同的挂载点注册不同的操作函数,以达到为不同协议的不同挂载点的报文进行不同处理的目的,为实现这个目的Netfilter定义了一个叫做nf_hook_ops的结构体,具体定义如下:
struct nf_hook_ops
{
struct
list_head list;
nf_hookfn
*hook;//函数指针,操作的具体执行者
struct module
*owner;
int
pf;//协议族
int
hooknum;//hook的类型
int
priority;//该操作的优先级,插入时使用
};
其中hook成员变量的原型为:
typedef unsigned int nf_hookfn(unsigned int
hooknum,
struct
sk_buff *skb,
const
struct net_device *in,
const
struct net_device *out,
int
(*okfn)(struct sk_buff *));//hook函数原型
Netfilter将不同协议的不同挂载点的操作函数都存放在一个全无变量nf_hooks中,数据包进入Netfilter后,会查找相应的hook操作,nf_hook对应的定义如下:
struct list_head
nf_hooks[NPROTO][NF_MAX_HOOKS] __read_mostly;//存放所有协议的hooks
综上所述,我们可以用如下的表来表示,netfilter的内部的整个数据和扩展流程:
图3.2 内部扩展机制
数据包在IP协议栈处理的过程中在经过挂载点时,就会进入Netfilter对报文做处理,NF_HOOK的整个调用流程可用如下的流程表来表示:
1、 整个hook的调用流程如下:
图3.3 Netfilter中包处理
其中NF_HOOK的定义如下:
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)
\
NF_HOOK_THRESH(pf,
hook, skb, indev, outdev, okfn, INT_MIN)