分类: LINUX
2014-10-16 16:55:08
原文地址:十、filter表报文过滤的实现 作者:guanglongxishui
Netfilter 中对报文的过滤默认是放在filter表中的。根据以上讲解的内容,要使用filter表来实现对报文的过滤,需要做如下两步:
1、建立filter表并注册表
2、实现hook函数并注册hook函数
代码文件路径:net/ipv4/netfilter/iptable_filter.c
Filter表在INPUT,OUTPUT,FORWARD三个点来设置hook函数,对到本机,转发,本机发送的三个方向上的报文进行过滤。
/*有效hook点*/
#define FILTER_VALID_HOOKS ((1 << NF_INET_LOCAL_IN) | \
(1 << NF_INET_FORWARD) | \
(1 << NF_INET_LOCAL_OUT))
/*初始化filter表用的rule项,每个chain里有一个默认rule,该rule 的target是 ACCEPT*/
static struct
{
struct ipt_replace repl;
struct ipt_standard
entries[3];
struct ipt_error term;
} initial_table __net_initdata = {
.repl = {
.name = "filter",
.valid_hooks = FILTER_VALID_HOOKS,
.num_entries = 4,
.size = sizeof(struct ipt_standard) * 3 + sizeof(struct
ipt_error),
.hook_entry = {
[NF_INET_LOCAL_IN]
= 0,
[NF_INET_FORWARD]
= sizeof(struct ipt_standard),
[NF_INET_LOCAL_OUT]
= sizeof(struct ipt_standard) * 2,
},
.underflow = {
[NF_INET_LOCAL_IN]
= 0,
[NF_INET_FORWARD]
= sizeof(struct ipt_standard),
[NF_INET_LOCAL_OUT]
= sizeof(struct ipt_standard) * 2,
},
},
.entries = {
IPT_STANDARD_INIT(NF_ACCEPT), /*
LOCAL_IN */
IPT_STANDARD_INIT(NF_ACCEPT), /*
FORWARD */
IPT_STANDARD_INIT(NF_ACCEPT), /*
LOCAL_OUT */
},
.term = IPT_ERROR_INIT, /* ERROR */
};
/*filter表*/
static const struct xt_table packet_filter = {
.name =
"filter",
.valid_hooks = FILTER_VALID_HOOKS,
.me = THIS_MODULE,
.af = NFPROTO_IPV4,
};
注册filter表
static int __net_init iptable_filter_net_init(struct net *net)
{
/* Register table */
net->ipv4.iptable_filter
=
ipt_register_table(net,
&packet_filter, &initial_table.repl);
if
(IS_ERR(net->ipv4.iptable_filter))
return PTR_ERR(net->ipv4.iptable_filter);
return 0;
}
初始化hook_ops结构体
static struct nf_hook_ops ipt_ops[]
__read_mostly = {
{
.hook = ipt_local_in_hook,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_IN,
.priority =
NF_IP_PRI_FILTER,
},
{
.hook = ipt_hook,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_FORWARD,
.priority =
NF_IP_PRI_FILTER,
},
{
.hook = ipt_local_out_hook,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_OUT,
.priority =
NF_IP_PRI_FILTER,
},
};
注册hook函数
static int __init iptable_filter_init(void)
{
int ret;
/* Register hooks */
ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
return ret;
}
现在来看看具体的hook函数实现
INPUT
static unsigned int ipt_local_in_hook(unsigned int hook,
struct sk_buff *skb,
const struct
net_device *in,
const struct
net_device *out,
int (*okfn)(struct
sk_buff *))
{
return ipt_do_table(skb, hook, in, out,
dev_net(in)->ipv4.iptable_filter);
}
FORWARD
static unsigned int
ipt_hook(unsigned int hook,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
return ipt_do_table(skb, hook, in, out,
dev_net(in)->ipv4.iptable_filter);
}
OUTPUT
static unsigned int
ipt_local_out_hook(unsigned int hook,
struct sk_buff *skb,
const struct
net_device *in,
const struct
net_device *out,
int (*okfn)(struct
sk_buff *))
{
/*对本机产生的一些小报文不进行过滤*/
/* root is playing with raw
sockets. */
if (skb->len <
sizeof(struct iphdr) ||
ip_hdrlen(skb) < sizeof(struct iphdr))
return NF_ACCEPT;
return ipt_do_table(skb, hook, in, out,
dev_net(out)->ipv4.iptable_filter);
}
从上面看出,三个hook函数最后都是调用 ipt_do_table函数来进行处理报文的。
raw表和mangle表的实现都和filter表一样,也都是调用ipt_do_table来进行表的遍历。这里就不进行详细分析了。
1、filter表的初始化和注册
2、HOOK函数的实现和注册
(未完待续)