首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

Linux Netfilter兑现机制和扩展技术

2012-08-01 
Linux Netfilter实现机制和扩展技术2.4.x的内核相对于2.2.x在IP协议栈部分有比较大的改动, Netfilter-ipta

Linux Netfilter实现机制和扩展技术

2.4.x的内核相对于2.2.x在IP协议栈部分有比较大的改动, Netfilter-iptables更是其一大特色,由于它功能强大,并且与内核完美结合,因此迅速成为Linux平台下进行网络应用扩展的主要利器,这些扩展不仅包括防火墙的实现--这只是Netfilter-iptables的基本功能--还包括各种报文处理工作(如报文加密、报文分类统计等),甚至还可以借助Netfilter-iptables机制来实现虚拟专用网(VPN)。本文将致力于深入剖析Netfilter-iptables的组织结构,并详细介绍如何对其进行扩展。Netfilter目前已在ARP、IPv4和IPv6中实现,考虑到IPv4是目前网络应用的主流,本文仅就IPv4的Netfilter实现进行分析。

要想理解Netfilter的工作原理,必须从对Linux IP报文处理流程的分析开始,Netfilter正是将自己紧密地构建在这一流程之中的。



图3 报文接收流程之协议栈阶段
Linux Netfilter兑现机制和扩展技术

如果报文需要转发,则在上图红箭头所指处调用ip_forward():


图4 报文转发流程
Linux Netfilter兑现机制和扩展技术

从上面的流程可以看出,Netfilter以NF_HOOK()的形式出现在报文处理的过程之中。

Netfilter框架为多种协议提供了一套类似的钩子(HOOK),用一个struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS]二维数组结构存储,一维为协议族,二维为上面提到的各个调用入口。每个希望嵌入Netfilter中的模块都可以为多个协议族的多个调用点注册多个钩子函数(HOOK),这些钩子函数将形成一条函数指针链,每次协议栈代码执行到NF_HOOK()函数时(有多个时机),都会依次启动所有这些函数,处理参数所指定的协议栈内容。

每个注册的钩子函数经过处理后都将返回下列值之一,告知Netfilter核心代码处理结果,以便对报文采取相应的动作:

NF_ACCEPT:继续正常的报文处理;

NF_DROP:将报文丢弃;

NF_STOLEN:由钩子函数处理了该报文,不要再继续传送;

NF_QUEUE:将报文入队,通常交由用户程序处理;

NF_REPEAT:再次调用该钩子函数。

nf_sockopts是在iptables进行初始化时通过nf_register_sockopt()函数生成的一个struct nf_sockopt_ops结构,对于ipv4来说,在net/ipv4/netfilter/ip_tables.c中定义了一个ipt_sockopts变量(struct nf_sockopt_ops),其中的set操作指定为do_ipt_set_ctl(),因此,当nf_sockopt()调用对应的set操作时,控制将转入net/ipv4/netfilter/ip_tables.c::do_ipt_set_ctl()中。

对于IPT_SO_SET_REPLACE命令,do_ipt_set_ctl()调用do_replace()来处理,该函数将用户层传入的struct ipt_replace和struct ipt_entry组织到filter(根据struct ipt_replace::name项)表的hook_entry[NF_IP_FORWARD]所指向的区域,如果是添加规则,结果将是filter表的private(struct ipt_table_info)项的hook_entry[NF_IP_FORWARD]和underflow[NF_IP_FORWARD]的差值扩大(用于容纳该规则),private->number加1。

2.5.4 规则应用过程

以上描述了规则注入核内iptables的过程,这些规则都挂接在各自的表的相应HOOK入口处,当报文流经该HOOK时进行匹配,对于与规则匹配成功的报文,调用规则对应的Target来处理。仍以转发的报文为例,假定filter表中添加了如上所述的规则:拒绝所有转发报文。

如1.2节所示,经由本地转发的报文经过路由以后将调用ip_forward()来处理,在ip_forward()返回前,将调用如下代码:

2.5.5 Netfilter的结构特点

由上可见,nf_hooks链表数组是联系报文处理流程和iptables的纽带,在iptables初始化(各自的init()函数)时,一方面调用nf_register_table()建立规则容器,另一方面还要调用nf_register_hook()将自己的挂钩愿望表达给Netfilter框架。初始化完成之后,用户只需要通过用户级的iptables命令操作规则容器(添加规则、删除规则、修改规则等),而对规则的使用则完全不用操心。如果一个容器内没有规则,或者nf_hooks上没有需要表达的愿望,则报文处理照常进行,丝毫不受Netfilter-iptables的影响;即使报文经过了过滤规则的处理,它也会如同平时一样重新回到报文处理流程上来,因此从宏观上看,就像在行车过程中去了一趟加油站。

Netfilter不仅仅有此高效的设计,同时还具备很大的灵活性,这主要表现在Netfilter-iptables中的很多部分都是可扩充的,包括Table、Match、Target以及Connection Track Protocol Helper,下面一节将介绍这方面的内容。

对于外出报文(源于本地或内网),使用内部地址在FORWARD/OUTPUT点匹配成功,执行ENCRYPT,从Netfilter中返回后作为本地IPIP_EXT协议的报文继续往外发送。

对于接收到的报文,如果协议号为IPPROTO_IPIP_EXT,则匹配IPIP_EXT的Match成功,否则将在INPUT点被丢弃;继续传送的报文从IP层传给IPIP_EXT的协议处理代码接收,在其中恢复内网IP的报文头后调用netif_rx()重新流入协议栈。此时的报文将在INPUT/FORWARD点匹配规则,并执行DECRYPT,只有通过了DECRYPT的报文才能继续传送到本机的上层协议或者内网。

附:iptables设置指令(样例):

iptables -t vpn -P FORWARD DROPiptables -t vpn -A OUTPUT -d 192.168.0.0/24 -j ENCRYPTiptables -t vpn -A INPUT -s 192.168.0.0/24 -m ipip_ah -j DECRYPTiptables -t vpn -A FORWARD -s 192.168.0.0/24 -d 192.168.1.0 -j DECRYPTiptables -t vpn -A FORWARD -s 192.168.1.0/24 -d 192.168.0.0/24 -j ENCRYPT

其中192.168.0.0/24是目的子网,192.168.1.0/24是本地子网

<!-- CMA ID: 21678 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file: dw-article-6.0-beta.xsl -->

参考资料

[Linus Torvalds,2003] Linux内核源码v2.4.21

[Paul Russell,2002] Linux netfilter Hacking HOWTO v1.2

[Paul Russell,2002] iptables源码v1.2.1a

[Paul Russell,2000] LinuxWorld: San Jose August 2000,Netfilter Tutorial

[Oskar Andreasson,2001] iptables Tutorial 1.0.9

热点排行