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

168 篇文章 0 订阅
63 篇文章 1 订阅

对于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规则的优化。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值