辛苗
摘 要:由于小型商业或自用网络中心无法投入大量财力物力对其进行全部防御,本文提出了一种自建入侵检测系统与防火墙联动策略的实现方法来实现该类网站中心的基本防护。利用Libnids库进行二次开发实现了自建入侵检测系统与防火墙联动,该策略在进行监听网络通信期间,当察觉到可疑的活动,系统就会自动设置新的防火墙规则,阻止与可疑IP主机间的全部连接。实验证明,通过硬件、软件的配合,可以有效对不符合规定的行为进行即时阻断和记录。
关键词:入侵检测;防火墙联动策略;Libnids;主动防御
1 引言
目前,在全球信息化的同时,各种攻击、防护技术和方法(如对工业控制系统的攻击、无界浏览器、网络刷票、免杀、网络身份证、云安全等)层出不穷。这些攻击和防护技术所带来的安全问题尤其突出,而对网络进行实时安全问题检测,识别不同信息安全攻击手段的威胁程度,并迅速做出解决方案,使其对网络信息安全所带来的风险和影响降到最低,是一种十分必要的网络安全防护措施之一。国内外围绕网络信息安全的研究十分活跃,其重要性不言而喻[1] [2]。
本文提了一种自建入侵检测系统与防火墙联动策略实现方法是一种将被动式入侵检测系统变为主动式防御方法,其弊端较主动式防御技术无论在风险方面还是其技术被不法分子利用方面都是极低的,且其十分灵活,造价及部署成本极低。
2 技术概述
防火墙可以比喻为办公室门口的警卫,用来检查进出者的身份。而入侵检测系统就像是网上的警报器,当发现入侵者时,指出入侵者的来历、他们正在做什么。入侵检测系统被视为防火墙之后的第二道安全闸门。
2.1 防火墙技术
防火墙技术,最初是针对 Internet 网络不安全因素所采取的一种保护措施。顾名思义,防火墙就是用来阻挡外部不安全因素影响的内部网络屏障,其目的就是防止外部网络用户未经授权的访问。它是一种计算机硬件防火墙件和软件的结合,使Internet與Intranet之间建立起一个安全网关(Security Gateway),从而保护内部网免受非法用户的侵入,防火墙主要由服务访问政策、验证工具、包过滤和应用网关4个部分组成,防火墙就是一个位于计算机和它所连接的网络之间的软件或硬件。该计算机流入流出的所有网络通信均要经过此防火墙。
防火墙的工作原理是按照事先规定的策略规则,监控所有通过防火墙的数据信息,严格按照策略执行通、断动作,同时保存日志信息,记录其五元组(通常是指由源IP地址,源端口,目的IP地址,目的端口,和传输层协议号这五个量组成的一个集合),以便方便网络管理员的检测和跟踪[3]。
防火墙的优点是策略性强,通过执行人为定制的安全策略,能过滤掉管理员知识体系中已有的不安全服务,拒绝可疑的访问,大大降低非法攻击的风险,提高网络安全系数[4]。
2.2 入侵检测系统
入侵检测系统是一个强大的网络入侵检测系统。它具有实时数据流量分析和记录IP网络数据包的能力,能够进行协议分析,对网络数据包内容进行搜索/匹配。它能够检测各种不同的攻击方式,对攻击进行实时报警。此外,很多入侵检测系统都是开源的,例如snort,具有很好的扩展性和可移植性,本文这事利用开源入侵检测系统进行二次设计实现与防火墙联动[5] [6]。入侵检测系统基本体系结构如图1所示:
如上图所示,入侵检测系统基本体系结构由4大软件模块组成,它们分别是:
(1)数据包嗅探模块——负责监听网络数据包,对网络进行分析;
(2) 预处理模块——该模块用相应的插件来检查原始数据包,从中发现原始数据的“行为”,如端口扫描,IP碎片等,数据包经过预处理后才传到检测引擎;
(3)检测模块——该模块是核心模块。当数据包从预处理器送过来后,检测引擎依据预先设置的规则检查数据包,一旦发现数据包中的内容和某条规则相匹配,就通知报警模块;
(4) 报警/日志模块——经检测引擎检查后的数据需要以某种方式输出。如果检测引擎中的某条规则被匹配,则会触发一条报警,这条报警信息会通过网络、UNIX socket、Windows Popup(SMB)、SNMP协议的trap命令传送给日志文件,甚至可以将报警传送给第三方插件(如SnortSam),另外报警信息也可以记入SQL数据库。
3 自建入侵检测系统与防火墙联动
本文使用Libnids(Library Network Intrusion Detection System)库进行二次编程实现自建入侵检测系统与防火墙联动。Libnids是一个用于网络入侵检测开发的专业编程接口。它实现了基于网络的入侵检测系统的基本框架,并提供了一些基本的功能。使用Libnids可以快速地构建基于网络的入侵检测系统[7] [8],并可以在此基础上进一步扩展开发。
3.1 开发实现TCP数据流重组
(1)TCP数据流重组
TCP报文在网络传输过程中会有失序,重复,还会有丢包的情况发生,在进行上层协议分析之前,需要对TCP报文进行重组以进行TCP报文的重新排序,丢弃重复的数据,并指示数据的丢失。简单的讲,重组仅关心TCP序号、应答号及数据,还有几个特殊的TCP标志(SYN,ACK,RST,FIN需特别处理) [9]。重组需要从SYN包获取一个启始序号,ACK标志表示应答序号有效,RST、FIN将设置数据流的结束标志,待所有数据接收完成,数据流才关闭[10]。
(2)利用Libnids二次开发实现TCP数据流重组
Libnids提供了TCP数据流重组的功能,它可以显示任何基于TCP协议的应用层协议。利用Libnids可以很好地实现显示TCP的连接过程,并对它们的传输数据进行详细的分析。Libnids的TCP数据流重组开发流程如下:
(a) 首先用函数nids_init()进行初始化;
(b) 调用函数nids_register_tcp()注册用于分析TCP连接和TCP连接状态的回调函数,主要的工作在此回调函数中实现;
(c) 调用函数nids_run()进入循环捕获数据包的状态。
Libnids的TCP数据流重组开发流程示意图如图2所示:
(3)回调函数tcp_dialog
对TCP流重组的回调函数的类型定义如下:
void tcp_dialog(struct tcp_stream* tcp_connection, void** arg);
其中参数tcp_connection描述的是一个TCP连接的所有信息。
下面提供了对其几个基本成员信息提取的方法,这些基本信息也是tcp_dailog所要实现完成的。
(a) 获取TCP连接的地址和端口对。
提取tcp_stream地址端口对成员:
struct tuple4 ip_and_port = tcp_connection->addr。
将目的ip地址转换为点式地址:
libnet_addr2name4( ip_and_port.saddr, 0 )。
获取TCP源/目的端口:
ip_and_port.source/ip_and_port.dest。
(b) 判断libnids状态。
switch( tcp_connection->nids_state )
{
case NIDS_JUST_EST:
// 表示TCP客户端与服务器建立连接状态
tcp_connection->client.collect++;
tcp_connection->server.collect++;
case NIDS_CLOSE:
// 表示TCP連接正常关闭
case NIDS_RESET:
// 表示TCP连接被RST关闭
case NIDS_DATA:
// 表示有新的数据到达,对新到达的数据进行解析
// 调用自定义函数
parse_newdata(struct tcp_stream* tcp_connection,char * AddBuf )
}
3.2 开发实现TCP端口扫描检测
(1) 实现端口扫描检测
在Libnids中提供了一些基本的检测技术,如对网络扫描攻击的检测(包括端口扫描攻击),以及对异常IP数据包、异常TCP数据包和异常UDP数据包的检测。Libnids针对端口扫描攻击的开发流程如下:
(a) 首先通过Libnids的全局参数对Libnids的一些环境参数进行设置,就端口扫描检测而言,此步骤完成的是注册端口扫描检测攻击的函数,方法如下:
nids_params.syslog = portscan_ids
其中nids_params为Libnids全局变量,成员syslog是一个函数指针,默认值为nids_syslog()函数。
在syslog函数中可以检测入侵攻击,如端口扫描攻击,也可以检测一些异常情况,如无效TCP标记。此处注册的是回调函数portscan_ids,其定义类型如下:
void portscan_ids(int type, int errnum, IPV4_HEADER* iph,struct host* hostinfo)
入口参数说明如下:
参数type为Libnids报警类型;
参数errnum为IP、TCP报警类型;
参数iph为IP数据包头结构,需要自定义,见common/pt_header.h;
参数hostinfo为扫描主机数据结构。
设置之后的环境参数对整个Libnids都有效。
(b) 完成检测攻击函数的注册后,接下来用函数nids_init()进行Libnids初始化。
(c) 最后用函数nids_run()进入循环捕获数据包的状态。
Libnids针对端口扫描攻击的开发流程示意如图3所示。
\
(2)扫描主机数据结构
struct scan
{
unsigned int addr;/* 被扫描者的IP(网络字节顺序)*/
unsigned short port;/* 被扫描端口号*/
unsigned char flags;/* TCP扫描类型(SYN、FIN、NULL扫描)*/
}
struct host
{
struct host* next;/* 下一个主机结点*/
struct host* prev;/* 前一个主机结点*/
unsigned addr;/* 扫描源IP地址*/
unsigned modtime;/* 时间*/
unsigned n_packets;/* 扫描次数*/
struct scan* packets;/* 扫描信息*/
}
(3) 端口扫描检测回调函数