您的位置:首页 > 理论基础 > 计算机网络

Linux网络防火墙【4】 Linux内核网络 iptables 之filter分析

2014-04-14 12:38 471 查看
对于iptables 而言, 其实 最核心的本质上就是注册在netfilter 链上的模块。不同版本的linux内核可能会有些不同,而且 现在linux 越来越复杂,比如filter封装的越来越多,3.20版本的filter 已经被封装了很多层,但是本质上 还是netfilter的module。


下面, 我以2.6.11版本的Linux 做一下简要的分析。 对于 更高版本的Linux 只要顺着 "找“, 最终还是会简化成 类似的思路。

iptable_filter.c
static int forward = NF_ACCEPT; //默认的filter策略
module_param(forward, bool, 0000); //可以设置的内核参数。

static int __init init(void)
{
int ret;

if (forward < 0 || forward > NF_MAX_VERDICT) {
printk("iptables forward must be 0 or 1\n");
return -EINVAL;
}

/* Entry 1 is the FORWARD hook */
initial_table.entries[1].target.verdict = -forward - 1;

/* Register table */
ret = ipt_register_table(&packet_filter, &initial_table.repl); //此处 注册了iptbles的表
if (ret < 0)
return ret;

/* Register hooks */
/*filter因为有三个hook点,所以注册了三个netfilter module, 分别是local_in forward local_out*/
ret = nf_register_hook(&ipt_ops[0]);    //此处才是真正注册了netfilter 模块,对应NF_IP_LOCAL_IN
if (ret < 0)
goto cleanup_table;

ret = nf_register_hook(&ipt_ops[1]);   //对应NF_IP_FORWARD
if (ret < 0)
goto cleanup_hook0;

ret = nf_register_hook(&ipt_ops[2]);   //对应NF_IP_LOCAL_OUT
if (ret < 0)
goto cleanup_hook1;

return ret;
/*对应错误处理,一定要到位。内核的崩溃是最严重的错误*/
cleanup_hook1:
nf_unregister_hook(&ipt_ops[1]);
cleanup_hook0:
nf_unregister_hook(&ipt_ops[0]);
cleanup_table:
ipt_unregister_table(&packet_filter);

return ret;
}

static void __exit fini(void)
{
unsigned int i;

for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
nf_unregister_hook(&ipt_ops[i]);

ipt_unregister_table(&packet_filter);
}

module_init(init);
module_exit(fini);


下面是关于上面注册参数的代码。可以看到ipt_ops[]对应上面代码的数组。 下面就是具体的结构体定义。

static struct nf_hook_ops ipt_ops[] = {
{
.hook = ipt_hook, /*具体filter的入口,下同*/
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_IN, /*模块的hook点*/
.priority = NF_IP_PRI_FILTER, /*优先级,对应filter raw nat等等的,按照不同的优先级进行处理*/
},
{
.hook = ipt_hook, //如上
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_FORWARD,
.priority = NF_IP_PRI_FILTER,
},
{
.hook = ipt_local_out_hook, //如上
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_OUT,
.priority = NF_IP_PRI_FILTER,
},
};

下面看看 hook函数。 主要 版本不一样, hook的形参 是不一样的,如何使用要根据具体的Linux版本来定义。
/* The work comes in here from netfilter.c. */
static unsigned int
ipt_hook(unsigned int hook,
struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
return ipt_do_table(pskb, hook, in, out, &packet_filter, NULL);
}可以看到 最终调用了ipt_do_table, 这是ipbtables规则处理的入口, 根据hook点 和 packet_fliter里面的iptables规则进行遍历,最终调用target。这里就不深入再去分析这个函数了,可以看到最终是 遍历对应的规则而已。

再看看locl_out的hook。

static unsigned int
ipt_local_out_hook(unsigned int hook,
struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
/* root is playing with raw sockets. */
if ((*pskb)->len < sizeof(struct iphdr)
|| (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
if (net_ratelimit())
printk("ipt_hook: happy cracking.\n");
return NF_ACCEPT;
}

return ipt_do_table(pskb, hook, in, out, &packet_filter, NULL);
}

可以看到也是调用的ipt_do_table函数, 还是遍历规则。

从上面可以看到, 最终都是遍历了Iptables的规则。 所以Iptables的规则, 也是提高性能的切入点, 这可以说是 网络吞吐量的一个瓶颈。提高网络吞吐量,最终还是转换为对iptables规则的优化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: