1. netfilter框架
Netfilter 是Linux内核中进行数据包过滤、连接跟踪、地址转换等的主要实现框架。当我们希望过滤特定的数据包或者需要修改数据包的内容再发送出去,这些动作主要都在netfilter中完成。
iptables工具就是用户空间和内核的Netfilter模块通信的手段,iptables命令提供很多选项来实现过滤数据包的各种操作,所以,我们在定义数据包过滤规则时,并不需要去直接修改内核中的netfilter模块,后面会讲到iptables命令如何作用于内核中的netfilter。
Netfilter的实质就是定义一系列的hook点(挂钩),每个hook点上可以挂载多个hook函数,hook函数中就实现了我们要对数据包的内容做怎样的修改、以及要将数据包放行还是过滤掉。数据包进入netfilter框架后,实际上就是依次经过所有hook函数的处理,数据包的命运就掌握在这些hook函数的手里。
本文基于内核版本2.6.31。
所有的hook点都放在一个全局的二维数组,每个hook点上的hook函数按照优先级顺序注册到一个链表中,注册的接口为nf_register_hook()。这个二维数组的定义如下:
struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS]__read_mostly;
其中NFPROTO_NUMPROTO 为netfilter支持的协议类型:
enum {
NFPROTO_UNSPEC= 0,
NFPROTO_IPV4 = 2,
NFPROTO_ARP = 3,
NFPROTO_BRIDGE= 7,
NFPROTO_IPV6 = 10,
NFPROTO_DECNET= 12,
NFPROTO_NUMPROTO,
};
我们看到枚举值并不连续,这是为了和协议族定义的值保持一致,因为注册hook函数的时候是根据协议族来注册的,如PF_INET=2,则对应的NFPROTO_IPV4=2。
NF_MAX_HOOKS是每种协议最多可挂的hook点的个数,它的值是8。如IPv4挂了5个,分别为:
enum nf_inet_hooks {
NF_INET_PRE_ROUTING,
NF_INET_LOCAL_IN,
NF_INET_FORWARD,
NF_INET_LOCAL_OUT,
NF_INET_POST_ROUTING,
NF_INET_NUMHOOKS
};
也就是说,对于IPv4协议来讲,一共有5个hook点,这5个hook点上注册的hook函数放在下列链表中:
Hook点 |
该hook点上注册的hook函数链表的表头 |
NF_INET_PRE_ROUTING |
nf_hooks[NFPROTO_IPV4][ NF_INET_PRE_ROUTING] |
NF_INET_LOCAL_IN |
nf_hooks[NFPROTO_IPV4][ NF_INET_LOCAL_IN] |
NF_INET_FORWARD |
nf_hooks[NFPROTO_IPV4][ NF_INET_FORWARD] |
NF_INET_LOCAL_OUT |
nf_hooks[NFPROTO_IPV4][ NF_INET_LOCAL_OUT] |
NF_INET_POST_ROUTING |
nf_hooks[NFPROTO_IPV4][ NF_INET_POST_ROUTING] |
对于发往本地的数据包,会依次经过NF_INET_PRE_ROUTING和NF_INET_LOCAL_IN两个hook点的处理。
对于本地向外发出去的数据包,会依次经过