发展迅速的网络防火墙功夫深入到第七层
作者:hanbin 来源:华夏收集
编者按在短短的几年里,防火墙的功能重心从网络层发展到了应用层。本文阐述了这种变迁的技术背景,以及未来的防火墙技术走向。
应用层攻击挑战传统防火墙
最近两年来,攻击者的兴趣明显从端口扫描和制造拒绝服务攻击(DoS Attack)转向了针对Web、E-mail甚至数据库等主流应用的攻击。传统的防火墙仅仅检查IP数据包的包头,而忽略了内容——如果用信件来做比喻,也就是只检查了信封而没有检查信纸。因此对这类应用层的攻击无能为力。可以说,仅仅靠第三层和第四层的IP地址和协议端口过滤的防火墙产品早已走到了尽头。
战火烧向七层
为了对抗应用层(OSI网络模型的第七层)的攻击,防火墙必须具备应用层的过滤能力,一些防火墙产品已经具备了这种能力。
如果把计算机网络比做一座建筑,传统的包过滤防火墙就是在企业内部网络和Internet之间的一系列并列的门。每道门都有安检人员对到达的包裹(IP数据包)进行逐一检查,若没有发现数据包含有异常代码便开门放行。攻击者常用的伎俩就是通过端口扫描来检查哪些门是敞开不设防的,然后加以利用。晚些时候出现的具有状态检测功能的防火墙可以检查哪些数据包是来自Internet对内部网络访问请求的应答。也就是说,安检人员能够鉴别那些不请自来的包裹。
但应用层攻击就要复杂得多,因为攻击数据包在绝大多数情况下是合法的数据包,不同的只是内容具有攻击性,而且因为IP数据包是分段传输的,其内容的判别需要将所有相关的包重组后才能准确进行。一旦这种攻击数据包通过了防火墙,它们通常会开始有条不紊地利用目标系统的漏洞制造缓冲区溢出,获得系统的控制权,然后以此为平台开始寻找周围其他系统的漏洞或者其他的蠕虫留下的后门,进而展开攻击。
防火墙的对策
对此,一些防火墙产品采取的应对措施是,针对每一类主流的应用, HTTP、SMTP、FTP和SQL Server数据库访问(基于RPC)都设置专门的过滤器,如果未来出现新的应用层威胁,还可以增加相应的过滤器。用户可以针对每一种过滤器进行应用相关的过滤设置,例如,可以通过限制任何HTTP访问请求的缓冲区不得超过3000个字节来防止一些蠕虫的攻击。在这种新的机制下,来自Internet的数据包被发送到各自的过滤器,过滤器会将数据包重组后进行内容扫描和判别。拿一封邮件来说,SMTP过滤器会等待相关的包到齐后,在转发之前重组邮件对其内容进行扫描,与已知类型的攻击进行比对,在确认这是正常流量后才允许通过。
经过正确配置的现代防火墙可以阻挡绝大多数已知的病毒邮件和攻击代码。虽然阻挡未知的病毒和攻击要困难得多,但是经过合理的策略设置通常是有效的。正确设置策略的基础是企业用户对于自身业务需求的正确理解,例如,多数企业的用户通常是没有必要通过邮件来传递可执行文件和Visual Basic脚本代码的。用户可以通过阻断含有这类可执行附件的邮件来对付一些未知的病毒。一旦真的需要发送这类文件,也可以设置更有针对性的策略,比如只允许IT部门的用户发送含有可执行文件附件邮件,或者允许用户接收除含有名为“Kournikova.jpg.vbs”的脚本附件之外的所有邮件。
安全与性能的矛盾
用户早已习惯于把安全性和性能看成是对立的,就像在机场的安检入口,检查的步骤越多,等待安检的队伍也就越长。对于防火墙来说,性能和安全的确是一对永远的矛盾,但是应用层过滤的功能对防火墙性能的影响并没有多数用户想象得那么大,一些防火墙标称每秒钟可处理超过1000个并发用户,同时保持每会话(Session)27Mbps的吞吐量。事实上,有些厂商通过硬件(ASIC)实现应用层的过滤引擎,能够达到更加接近线速(可理解为以太网交换机的处理极限)的处理能力。
新的挑战
具有应用层过滤功能的防火墙可以更有效地阻挡当前多数病毒和攻击程序,但新的安全威胁的不断出现又对防火墙提出了新的挑战。攻击的来源正在变得更加复杂,而攻击的手段也愈加高明,最近垃圾邮件与攻击代码的结合就是一个典型的例证。这一方面需要防火墙设备对于应用层的内容有更好的认知和智能判别的能力,另一方面也需要防火墙更多地与其他的安全设备和应用有效配合,从而实现更加有力的防护。
Linux系统中防火墙的框架及简单分析
作者:hanbin 来源:华夏收集
Netfilter提供了一个抽象、通用化的框架,该框架定义的一个子功能的实现就是包过滤子系统框架包含以下五部分:
1. 为每种网络协议(IPv4、IPv6等)定义一套钩子函数(IPv4定义了5个钩子函数), 这些钩子函数在数据报流过协议栈的几个关键点被调用。在这几个点中,协议栈将把数据报及钩子函数标号作为参数调用Netfilter框架。
2. 内核的任何模块可以对每种协议的一个或多个钩子进行注册,实现挂接,这样当某个数据包被传递给Netfilter框架时,内核能检测是否有任何模块对该协议和钩子函数进行了注册。若注册了,则调用该模块的注册时使用的回调函数,这样这些模块就有机会检查(可能还会修改)该数据包、丢弃该数据包及指示Netfilter将该数据包传入用户空间的队列。
3 .那些排队的数据包是被传递给用户空间的异步地进行处理。一个用户进程能检查数据包,修改数据包,甚至可以重新将该数据包通过离开内核的同一个钩子函数中注入到内核中。
4. 任何在IP层要被抛弃的IP数据包在真正抛弃之前都要进行检查。例如允许模块检查IP-Spoofed包(被路由抛弃)。
5.IP层的五个HOOK点的位置如下所示 :
(1)NF_IP_PRE_ROUTING:刚刚进入网络层的数据包通过此点(刚刚进行完版本号,校验 和等检测), 源地址转换在此点进行;IP_Input.c中IP_Rcv调用。
(2)NF_IP_LOCAL_IN:经路由查找后,送往本机的通过此检查点,INPUT包过滤在此点进行;IP_local_deliver中调用
(3)NF_IP_FORWARD:要转发的包通过此检测点,FORWORD包过滤在此点进行;
(4)NF_IP_POST_ROUTING:所有马上便要通过网络设备出去的包通过此检测点,内置的目的地址转换功能(包括地址伪装)在此点进行;
(5)NF_IP_LOCAL_OUT:本机进程发出的包通过此检测点,OUTPUT包过滤在此点进行。
这些点是已经在内核中定义好的,内核模块能够注册在这些HOOK点进行的处理,可使用nf_register_hook函数指定。在数据报经过这些钩子函数时被调用,从而模块可以修改这些数据报,并向Netfilter返回如下值:
NF_ACCEPT 继续正常传输数据报
NF_DROP 丢弃该数据报,不再传输
NF_STOLEN 模块接管该数据报,不要继续传输该数据报
NF_QUEUE 对该数据报进行排队(通常用于将数据报给用户空间的进程进行处理)
NF_REPEAT 再次调用该钩子函数
一个基于Netfilter框架的、称为IPtables的数据报选择系统在Linux2.4内核中被应用,其实它就是IPchains的后继工具,但却有更强的可扩展性。内核模块可以注册一个新的规则表(table),并要求数据报流经指定的规则表。这种数据报选择用于实现数据报过滤(filter表),网络地址转换(Nat表)及数据报处理(Mangle表)。 Linux2.4内核提供的这三种数据报处理功能都基于Netfilter的钩子函数和IP表。它们是独立的模块,相互之间是独立的。它们都完美的集成到由Netfileter提供的框架中。
包过滤
Filter表格不会对数据报进行修改,而只对数据报进行过滤。IPtables优于IPchains的一个方面就是它更为小巧和快速。它是通过钩子函数NF_IP_LOCAL_IN, NF_IP_FORWARD及NF_IP_LOCAL_OUT接入Netfilter框架的。因此对于任何一个数 报只有一个地方对其进行过滤。这相对IPchains来说是一个巨大的改进,因为在IPchains中一个被转发的数据报会遍历三条链。
NAT
NAT表格监听三个Netfilter钩子函数:NF_IP_PRE_ROUTING、NF_IP_POST_ROUTING及NF_IP_LOCAL_OUT。 NF_IP_PRE_ROUTING实现对需要转发的数据报的源地址进行地址转换而NF_IP_POST_ROUTING则对需要转发的数据包的目的地址进行地址转换。对于本地数据报的目的地址的转换则由NF_IP_LOCAL_OUT来实现。NAT表格不同于filter表格,因为只有新连接的第一个数据报将遍历表格,而随后的数据报将根据第一个数据报的结果进行同样的转换处理。NAT表格被用在源NAT,目的NAT,伪装(其是源NAT的一个特例)及透明代理(其是目的NAT的一个特例)。
数据报处理(Packet Mangling)
Mangle表格在NF_IP_PRE_ROUTING和NF_IP_LOCAL_OUT钩子中进行注册。使用 mangle表,可以实现对数据报的修改或给数据报附上一些带外数据。当前mangle表支持修改TOS位及设置skb的nfmard字段。
源码分析
如果我们想加入自己的代码,便要用nf_register_hook函数,其函数原型为:
int nf_register_hook(struct nf_hook_ops *reg)
struct nf_hook_ops
{
struct list_head list;
/* User fills in from here down. */
nf_hookfn *hook;
int pf;
int hooknum;
/* Hooks are ordered in ascending priority. */
int priority;
};
我们的工作便是生成一个struct nf_hook_ops结构的实例,并用nf_register_hook将其HOOK上。其中list项我们总要初始化为{NULL,NULL};由于一般在IP层工作,pf总是PF_INET;hooknum就是我们选择的HOOK点;一个HOOK点可能挂多个处理函数,谁先谁后,便要看优先级,即priority的指定了。Netfilter_IPv4.h中用一个枚举类型指定了内置的处理函数的优先级:
enum nf_IP_hook_priorities {
NF_IP_PRI_FIRST = INT_MIN,
NF_IP_PRI_CONNTRACK = -200,
NF_IP_PRI_MANGLE = -150,
NF_IP_PRI_NAT_DST = -100,
NF_IP_PRI_FILTER = 0,
NF_IP_PRI_NAT_SRC = 100,
NF_IP_PRI_LAST = INT_MAX,
};
Hook是提供的处理函数,也就是我们的主要工作,其原型为:
unsigned int nf_hookfn(unsigned int hooknum,
struct sk_buff **skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *));
它的五个参数将由NFHOOK宏传进去。nf_register_hook根据reg中注册的协议簇类型和优先级在nf_hooks中找到相应的位置并插入到此表中。_hooks[NPROTO][NF_MAX_HOOKS]在Netfilter初始化时(Netfilter_init/Netfilter.c,而它在sock_init时调用)已经初始为一个空表。
例如IPtable在初始化时(init/IPtable_filter.c)调用nf_register_hook注册他的hook函数。
static struct nf_hook_ops IPt_ops[]
= { { { NULL, NULL }, IPt_hook, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_FILTER },
{ { NULL, NULL }, IPt_hook, PF_INET, NF_IP_FORWARD, NF_IP_PRI_FILTER },
{ { NULL, NULL }, IPt_local_out_hook, PF_INET, NF_IP_LOCAL_OUT,
NF_IP_PRI_FILTER }
};
mangle在init/IPtable_mangle.c中注册它自己的hook函数。
static struct nf_hook_ops IPt_ops[]
= { { { NULL, NULL }, IPt_hook, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_MANGLE },
{ { NULL, NULL }, IPt_local_out_hook, PF_INET, NF_IP_LOCAL_OUT,
{NF_IP_PRI_MANGLE }
};
NAT在init/IP_nat_standalone.c中注册它自己的hook函数
/*包过滤前,更改目的地址*/
static struct nf_hook_ops IP_nat_in_ops