1、什么是Netfilter
Netfilter是Linux 2.4.x引入的一个子系统,它作为一个通用的、抽象的框架,提供一整套的hook函数的管理机制,使得诸如数据包过滤、网络地址转换(NAT)和基于协议类型的连接跟踪成为了可能。
iptables是Linux下功能强大的应用层防火墙工具, 说到iptables必然提到Netfilter,iptables是应用层的,其实质是一个定义规则的配置工具,而核心的数据包拦截和转发是Netfiler。Netfilter是Linux操作系统核心层内部的一个数据包处理模块。iptables和Netfilter关系如图1所示。
2、Netfilter的工作原理
Netfilter防火墙的内核模块为了对经过内核TCP/IP协议栈的不同类型数据包能够加以多种手段的控制和处理,在数据包经过协议栈的游历路线之中,分别选择了5个挂接点,Netfilter在netfilter_ipv4.h中将这个五个点重新命了个名,分别被命名为PRE_ROUTING、LOCAL_IN、FORWARD、LOCAL_OUT以及POST_ROUTING。数据包的传输流程以及Netfilter在IPV4协议中的挂载点结构如图2所示。
每个挂载点上,有很多已经按照预先注册了的回调函数(也被称为钩子函数),对于每个到来的数据包都会依次经过这些挂载点上的钩子函数的处理,从而判断数据包的是否继续传输。
5个挂载点在IPV4协议栈中定义的钩子函数,分别是NF_IP_PRE_ROUTING、NF_IP_LOCAL_IN、NF_IP_FORWARD、NF_IP_LOCAL_OUT、NF_IP_POST_ROUTING,这些函数的具体功能如下所示。
①NF_IP_PRE_ROUTING:进入的网络数据包在路由查找之前,在ip_rcv()函数(ip_rcv()是Linux核心网络堆栈中用于接收IPV4数据包的主要函数)中被处理并经过钩子点。在此之前,系统只对IP包头中的协议版本、包长度、校验和等进行简单的检查;
②NF_IP_LOCAL_IN:所有目的地址为本机的数据包将在ip_local_device()函数中处理,并流经该钩子点,iptables在这里设置过滤规则对流入数据包进行过滤;
③NF_IP_FORWARD:这是Linux防火墙最重要的钩子点,所有经过防火墙转发,目的地址非本机的数据包将在这里被处理。该钩子点在ip_forward()函数中被调用;
④NF_IP_LOCAL_OUT:所有从本机产生并发送出去的数据包都会经过该钩子点;
⑤NF_IP_POST_ROUTING:在数据包被最终发送至物理介质之前,可以在该点引入数据包的处理,该位置适合做SNAT(Source Network Address Translation)或统计工作。
每个注册的钩子函数经过处理后都将返回下列值之一,告知Netfilter核心代码处理结果,以便对数据包采取相应的动作。
NF_ACCEPT:表明该数据包还是被接受的并且该数据包应当被递交到网络协议栈的下一个阶段;
NF_DROP:表明丢弃该数据报,不再传输;
NF_STOLEN:表明该钩子函数将从此开始对数据包进行处理,并且Netfilter应当放弃对该数据包做任何处理,但是这并不意味着该数据包的资源已经被释放了;
NF_QUEUE:表明是将数据包发送到用户空间,等待在用户空间的处理程序进行处理;
NF_REPEAT:表明再次调用该钩子喊出,应当谨慎使用这个值,以免造成死循环。
3、Netfilter过滤技术的实现
(1)基于接口过滤
基于接口的过滤时所能够做的最简单的过滤技术。利用钩子函数nf_hookfn中的net_device结构体的name键值,可以根据数据包的目的接口名或源接口名来丢弃这些数据包。
(2)基于IP地址的过滤
类似基于接口的数据包过滤技术,基于源/目的IP地址的数据包过滤技术也较为简单。但基于IP地址的过滤技术需要调用结构体sk_buff的数据。通常建立一个接口体sk_buf的指针,并指向结构体数据,从而获取数据包中网络层头部信息,从而获取IP地址,进而与过滤规则中的IP地址进行比对。
(3)基于TCP端口的过滤
防火墙要执行的另一个简单的规则就是基于TCP目的端口哦的数据包过滤,这比检验IP地址略微复杂。因为要创建一个指向TCP头的指针,只需创建一个指向结构体的指针tcphdr,并将它指向数据包中的IP头之后,就可获得一个TCP头指针了。利用TCP头指针读取数据包的TCP端口的信息,并与过滤规则中定义的过滤端口作比较,如果数据包的TCP端口与想抛弃数据包的指定端口匹配,数据包就会被丢弃。
(4)基于数据包内容的过滤
在结构图sk_buff中吗,成员data是数据包内容。利用sb->data可以访问得到数据包内容,通过读取数据包中的内容数据,并与过滤规则中定义的关键字符串进行比较确定是否匹配,匹配规则按照规则定义的目标动作来处理,不匹配表示该数据包通过了过滤规则,由此实现对数据包内容的过滤。