PersonalCorpus 版 (精华区)
发信人: glees (我心底的中国), 信区: Hacker
标 题: ◆ 拒绝服务攻击原理及解决方法
发信站: 哈工大紫丁香 (2001年10月01日10:19:04 星期一), 站内信件
◆ 拒绝服务攻击原理及解决方法
出处:NCOD全球华人信息安全及黑客技术交流同盟
日期:2000-9-19 翻译:广州寒路 8/28/2000
Internet给全世界的人们带来了无限的生机,真正实现了无国界的全球村。但是还有很
多困绕我们的因素,象IP地址的短缺,大量带宽的损耗,以及政府规章的限制和编程技
术的不足。现在,由于多年来网络系统累积下了无数的漏洞,我们将面临着更大的威胁
,网络中潜伏的好事者将会以此作为缺口来对系统进行攻击,我们也不得不为以前的疏
忽付出更大的努力。虽然大多的网络系统产品都标榜着安全的旗号,但就我们现在的网
络协议和残缺的技术来看,危险无处不在。
拒绝服务攻击是一种遍布全球的系统漏洞,黑客们正醉心于对它的研究,而无数的网络
用户将成为这种攻击的受害者。Tribe Flood Network, tfn2k, smurf, targa…还有许
多的程序都在被不断的开发出来。这些程序想瘟疫一样在网络中散布开来,使得我们的
村落更为薄弱,我们不得不找出一套简单易用的安全解决方案来应付黑暗中的攻击。
在这篇文章中我们将会提供:
· 对当今网络中的拒绝服务攻击的讨论。
· 安全环境中的一些非技术性因素以及我们必须克服的一些障碍问题。
· 如何认清产品推销商所提供的一些谎言。
在我们正式步入对这些问题的技术性讨论之前,让我们先从现实的生活中的实际角度来
看一下这些困绕我们的问题。
当前的技术概况
在我们进入更为详细的解决方案之前,让我们首先对问题做一下更深入的了解。
与安全相关的这些小问题如果详细来讲的话都能成为一个大的章节,但限于篇幅的原因
,我们只能先作一下大体的了解。
· 软件弱点是包含在操作系统或应用程序中与安全相关的系统缺陷,这些缺陷大多是由
于错误的程序编制,粗心的源代码审核,无心的副效应或一些不适当的绑定所造成的。
根据错误信息所带来的对系统无限制或者未经许可的访问程度,这些漏洞可以被分为不
同的等级。
· 典型的拒绝服务攻击有如下两种形式:资源耗尽和资源过载。当一个对资源的合理请
求大大超过资源的支付能力时就会造成拒绝服务攻击(例如,对已经满载的Web服务器进
行过多的请求。)拒绝服务攻击还有可能是由于软件的弱点或者对程序的错误配置造成
的。区分恶意的拒绝服务攻击和非恶意的服务超载依赖于请求发起者对资源的请求是否
过份,从而使得其他的用户无法享用该服务资源。
· 错误配置也会成为系统的安全隐患。这些错误配置通常发生在硬件装置,系统或者应
用程序中。如果对网络中的路由器,防火墙,交换机以及其他网络连接设备都进行正确
的配置会减小这些错误发生的可能性。如果发现了这种漏洞应当请教专业的技术人员来
修理这些问题。
如果换个角度,也可以说是如下原因造成的:
· 错误配置。错误配置大多是由于一些没经验的,无责任员工或者错误的理论所导致的
。开发商一般会通过对您进行简单的询问来提取一些主要的配置信息,然后在由经过专
业培训并相当内行的专业人士来解决问题。
· 软件弱点。由于使用的软件几乎完全依赖于开发商,所以对于由软件引起的漏洞只能
依靠打补丁,安装hot fixes和Service packs来弥补。当某个应用程序被发现有漏洞存
在,开发商会立即发布一个更新的版本来修正这个漏洞。
· 拒绝服务攻击。拒绝服务攻击大多是由于错误配置或者软件弱点导致的。某些DoS攻
击是由于开发协议固有的缺陷导致的,某些DoS攻击可以通过简单的补丁来解决,还有一
些导致攻击的系统缺陷很难被弥补。最后,还有一些非恶意的拒绝服务攻击的情况,这
些情况一般是由于带宽或者资源过载产生瓶颈导致的,对于这种问题没有一个固定的解
决方案。
深入DoS
DoS的攻击方式有很多种。最基本的DoS攻击就是利用合理的服务请求来占用过多的服务
资源,致使服务超载,无法响应其他的请求。这些服务资源包括网络带宽,文件系统空
间容量,开放的进程或者向内的连接。这种攻击会导致资源的匮乏,无论计算机的处理
速度多么快,内存容量多么大,互连网的速度多么快都无法避免这种攻击带来的后果。
因为任何事都有一个极限,所以,总能找到一个方法使请求的值大于该极限值,因此就
会使所提供的服务资源匮乏,象是无法满足需求。千万不要自认为自己拥有了足够宽的
带宽就会有一个高效率的网站,拒绝服务攻击会使所有的资源变得非常渺小。
传统上,攻击者所面临的主要问题是网络带宽,由较小的网络规模和较慢的网络速度,
无法使攻击者发出过多的请求,然而,类似"the ping of death"的攻击类型紧需要很少
量的包就可以摧毁一个没有打过补丁的UNIX系统。当然,多数的DoS攻击还是需要相当大
的带宽的,但是高带宽是大公司所拥有的,而以个人为主的黑客很难享用。为了克服这
个缺点,恶意的攻击者开发了分布式的攻击。这样,攻击者就可以利用工具集合许多的
网络带宽来对同一个目标发送大量的请求。
以下的两种情况最容易导致拒绝服务攻击:
· 由于程序员对程序错误的编制,导致系统不停的建立进程,最终耗尽资源,只能重新
启动机器。不同的系统平台都会采取某些方法可以防止一些特殊的用户来占用过多的系
统资源,我们也建议尽量采用资源管理的方式来减轻这种安全威胁。
· 还有一种情况是由磁盘存储空间引起的。假如一个用户有权利存储大量的文件的话,
他就有可能只为系统留下很小的空间用来存储日志文件等系统信息。这是一种不良的操
作习惯,会给系统带来隐患。这种情况下应该对系统配额作出考虑。
从安全的角度来看,本地的拒绝服务攻击可以比较容易的追踪并消除。而我们这篇文章
主要是针对于网络环境下的DoS攻击。下面我们大体讨论一下较为常见的基于网络的拒绝
服务攻击:
· Smurf (directed broadcast)。广播信息可以通过一定的手段(通过广播地址或其他
机制)发送到整个网络中的机器。当某台机器使用广播地址发送一个ICMP echo请求包时
(例如PING),一些系统会回应一个ICMP echo回应包,也就是说,发送一个包会收到许
多的响应包。Smurf攻击就是使用这个原理来进行的,当然,它还需要一个假冒的源地址
。也就是说在网络中发送源地址为要攻击主机的地址,目的地址为广播地址的包,会使
许多的系统响应发送大量的信息给被攻击主机(因为他的地址被攻击者假冒了)。使用
网络发送一个包而引出大量回应的方式也被叫做"放大器",这些smurf放大器可以在www
.netscan.org网站上获得,一些无能的且不负责任的网站仍有很多的这种漏洞。
· SYN flooding 一台机器在网络中通讯时首先需要建立TCP握手,标准的TCP握手需要
三次包交换来建立。一台服务器一旦接收到客户机的SYN包后必须回应一个SYN/ACK包,
然后等待该客户机回应给它一个ACK包来确认,才真正建立连接。然而,如果只发送初始
化的SYN包,而不发送确认服务器的ACK包会导致服务器一直等待ACK包。由于服务器在有
限的时间内只能响应有限数量的连接,这就会导致服务器一直等待回应而无法响应其他
机器进行的连接请求。
· Slashdot effect 这种攻击手法使web服务器或其他类型的服务器由于大量的网络传
输而过载,一般这些网络流量是针对某一个页面或一个链接而产生的。当然这种现象也
会在访问量较大的网站上正常发生,但我们一定要把这些正常现象和拒绝服务攻击区分
开来。如果您的服务器突然变得拥挤不堪,甚至无法响应再多的请求时,您应当仔细检
查一下这个资源匮乏的现象,确认在10000次点击里全都是合法用户进行的,还是由500
0个合法用户和一个点击了5000次的攻击者进行的。
拒绝服务一般都是由过载导致的,而过载一般是因为请求到达了极限。
拒绝服务攻击的发展
由于我们防范手段的加强,拒绝服务攻击手法也在不断的发展。
Tribe Flood Network (tfn) 和tfn2k引入了一个新概念:分布式。这些程序可以使得分
散在互连网各处的机器共同完成对一台主机攻击的操作,从而使主机看起来好象是遭到
了不同位置的许多主机的攻击。这些分散的机器由几台主控制机操作进行多种类型的攻
击,如UDP flood, SYN flood等。
操作系统和网络设备的缺陷在不断地被发现并被黑客所利用来进行恶意的攻击。如果我
们清楚的认识到了这一点,我们应当使用下面的两步来尽量阻止网络攻击保护我们的网
络:
A)尽可能的修正已经发现的问题和系统漏洞。
B)识别,跟踪或禁止这些令人讨厌的机器或网络对我们的访问。
我们先来讨论一下B),在B)中我们面临的主要问题是如何识别那些恶意攻击的主机,
特别是使用拒绝服务攻击的机器。因为这些机器隐藏了他们自己的地址,而冒用被攻击
者的地址。攻击者使用了数以千记的恶意伪造包来使我们的主机受到攻击。"tfn2k"的原
理就象上面讲的这么简单,而他只不过又提供了一个形象的界面。假如您遭到了分布式
的拒绝服务攻击,实在是很难处理。
解决此类问题的一些专业手段----包过滤及其他的路由设置
有一些简单的手法来防止拒绝服务式的攻击。最为常用的一种当然是时刻关注安全信息
以期待最好的方法出现。管理员应当订阅安全信息报告,实时的关注所有安全问题的发
展。:)
第二步是应用包过滤的技术,主要是过滤对外开放的端口。这些手段主要是防止假冒地
址的攻击,使得外部机器无法假冒内部机器的地址来对内部机器发动攻击。
我们可以使用Cisco IOS来检查路由器的详细设置,当然,它也不仅限于Cisco的设备,
但由于现在Cisco设备在网络中占有了越来越多的市场份额(83%),所以我们还是以它
为例子,假如还有人有其他的例子,我们也非常高兴你能提出您的宝贵信息。
登陆到将要配置的路由器上,在配置访问控制列表之前先初始化一遍:
c3600(config)#access-list 100 permit ip 207.22.212.0 0.0.0.255 any
c3600(config)#access-list 100 deny ip any any
然后我们假设在路由器的S0口上进行ACL的设置,我们进入S0口,并进入配置状态:
c3600(config)#int ser 0
c3600(config-if)#ip access-group 100 out
通过显示access-list来确认访问权限已经生效:
c3600#sho access-lists 100
Extended IP access list 100
permit ip 207.22.212.0 0.0.0.255 any (5 matches)
deny ip any any (25202 matches)
对于应该使用向内的包过滤还是使用向外的包过滤一直存在着争论。RFC 2267建议在全
球范围的互连网上使用向内过滤的机制,但是这样会带来很多的麻烦,在中等级别的路
由器上使用访问控制列表不会带来太大的麻烦,但是已经满载的骨干路由器上会受到明
显的威胁。
另一方面,ISP如果使用向外的包过滤措施会把过载的流量转移到一些不太忙的设备上。
ISP也不关心消费者是否在他们的边界路由器上使用这种技术。当然,这种过滤技术也
并不是万无一失的,这依赖于管理人员采用的过滤机制。
我们经常会听到设备销售或集成商这样的推脱之词,他们总是说使用ACL会导致路由器和
网络性能的下降。ACL确实会降低路由器的性能并加重CPU的负载,但这是微乎其微的。
我们曾经在Cisco 2600 和3600系列路由器上作过实验:
以下是不使用和使用ACL时的对照表:
Test Speed w/o ACL (Mbps) w/ ACL (Mbps) w/o ACL (total time) w/ ACL (total t
ime) % change
Cisco 2600 100Mbps -》 100 Mbps File transfers 36.17 Mbps 35.46 Mbps 88.5 90
.2 2.50%
Cisco 3600 10Mbps -》 10Mbps File transfers 7.95 Mbps 8.0Mbps 397 395 0.30%
使用的路由器配置如下:
· Cisco 3640 (64MB RAM, R4700 processor, IOS v12.0.5T)
· Cisco 2600 (128MB RAM, MPC860 processor, IOS v12.0.5T)
由表我们可以看出,在使用ACL前后对路由器性能的影响并不是很大。
使用DNS来跟踪匿名攻击
也许大家仍旧保存着侥幸心理,认为这些互连网上给我们带来无数麻烦DoS漏洞或许随着
路由器包过滤,网络协议升级到IPv6或者随时的远程响应等手段变得越来越不重要。但
从一个具有责任感的网管的观点来看,我们的目标并不是仅仅阻止拒绝服务攻击,而是
要追究到攻击的发起原因及操作者。
当网络中有人使用假冒了源地址的工具(如tfn2k)时,我们虽然没有现成的工具来确认
它的合法性,但我们可以通过使用DNS来对其进行分析:
假如攻击者选定了目标www.technotronic.com,他必须首先发送一个DNS请求来解析这个
域名,通常那些攻击工具工具会自己执行这一步,调用gethostbyname()函数或者相应的
应用程序接口,也就是说,在攻击事件发生前的DNS请求会提供给我们一个相关列表,我
们可以利用它来定位攻击者。
使用现成工具或者手工读取DNS请求日志,来读取DNS可疑的请求列表都是切实可行的,
然而,它有三个主要的缺点:
l 攻击者一般会以本地的DNS为出发点来对地址进行解析查询,因此我们查到的DNS请求
的发起者有可能不是攻击者本身,而是他所请求的本地DNS服务器。尽管这样,如果攻击
者隐藏在一个拥有本地DNS的组织内,我们就可以把该组织作为查询的起点。
l 攻击者有可能已经知道攻击目标的IP地址,或者通过其他手段(host, ping)知道了
目标的IP地址,亦或是攻击者在查询到IP地址后很长一段时间才开始攻击,这样我们就
无法从DNS请求的时间段上来判断攻击者(或他们的本地服务器)。
l DNS对不同的域名都有一个却省的存活时间,因此攻击者可以使用存储在DNS缓存中的
信息来解析域名。为了更好做出详细的解析记录,您可以把DNS却省的TTL时间缩小,但
这样会导致DNS更多的去查询所以会加重网络带宽的使用。
在许多情况下,只要您拥有足够的磁盘空间,记录所有的DNS请求并不是一种有害的做法
。在BIND8.2中做记录的话,可以在named.conf中假如下面的几行:
logging {
channel requestlog { file "dns.log"; };
category queries { requestlog; };
};
使用 ngrep来处理tfn2k 攻击
根据使用DNS来跟踪tfn2k驻留程序的原理,现在已经出现了称为ngrep的实用工具。经过
修改的ngrep(参见附录)可以监听大约五种类型的tfn2k拒绝服务攻击(targa3, SYN f
lood, UDP flood, ICMP flood 和 smurf),它还有一个循环使用的缓存用来记录DNS和
ICMP请求。如果ngrep发觉有攻击行为的话,它会将其缓存中的内容打印出来并继续记录
ICMP回应请求。假如攻击者通过ping目标主机的手段来铆定攻击目标的话,在攻击过程
中或之后记录ICMP的回应请求是一种捕获粗心的攻击者的方法。由于攻击者还很可能使
用其他的服务来核实其攻击的效果(例如web),所以对其他的标准服务也应当有尽量详
细的日志记录。
还应当注意,ngrep采用的是监听网络的手段,因此,ngrep无法在交换式的环境中使用
。但是经过修改的ngrep可以不必和你的DNS在同一个网段中,但是他必须位于一个可以
监听到所有DNS请求的位置。经过修改的ngrep也不关心目标地址,您可以把它放置在DM
Z网段,使它能够检查横贯该网络的tfn2k攻击。从理论上讲,它也可以很好的检测出对
外的tfn2k攻击。
运行 ngrep, 您将看到:
[root@lughnasad ngrep]# ./ngrep
Ngrep with TFN detection modifications by wiretrip / www.wiretrip.net
Watching DNS server: 10.0.0.8
interface: eth0 (10.0.0.0/255.255.0.0)
从这里开始ngrep将监听tfn2k攻击,如果检测到攻击, ngrep将在屏幕上打印:
Sun Jan 9 17:30:01 2000
A TFN2K UDP attack has been detected!
Last (5000) DNS requests:
《list of IPs that made DNS requests, up to DNS_REQUEST_MAX length》
Last (1000) ICMP echo requests (pings):
《list of IPs that made ICMP echo requests, up to ICMP_REQUEST_MAX length》
Incoming realtime ICMP echo requests (pings):
《all ICMP echo requests since the attack was detected》
以上的列表并不是唯一的,可以对它进行调整让他不仅显示是谁请求,而且请求多少次
,频率为多少等等。在ICMP flood事件中,ICMP回应请求的报告中将不包括做为tfn2k
flood一部分的ICMP包。Ngrep还可以报告检测出来的除smurf之外的攻击类型(TARGA,
UDP, SYN, ICMP等)。混合式的攻击在缺省情况下表现为ICMP攻击,除非你屏蔽了向内
的ICMP回应请求,这样它就表现为UDP或SYN攻击。这些攻击的结果都是基本类似的。
附录- Ngrep.c with tfn2k detection
以下的代码在使用前应当更改一些参数。
#define DNS_REQUEST_MAX 5000
#define ICMP_REQUEST_MAX 1000
通知ngrep最大的请求跟踪数(在检测攻击之前)。传输较为繁忙的网站应当增加这一数
值(网络流量较为繁忙的网站DNS的请求数最好在10,000,而ICMP请求为2000-3000)
#define FLOOD_THRESHOLD 20
用在10秒中内有多少同一类型的攻击包来确认为真正的攻击。数目设计的越大,程序报
受攻击的可能性就越小。假如您老是收到错误的警报,那么您应当增加一下这个数值。
#define DNS_SERVER_IP "10.0.0.8"
Ngrep通过监视DNS服务器的53端口的UDP包来跟踪向内的DNS请求(只有UDP)。因此,n
grep需要知道您的DNS服务器的IP地址。
我们的设备可能会有多个DNS服务器,但我们认为对一台DNS服务器的支持足以证明这项
技术的能力。
#define TTL_THRESHOLD 150
tfn2k SYN flood 攻击使用的 TTL值通常在200-255的范围内。估计到攻击者与目标主机
之间不止50跳,因此我们可以只查找TTL时间高于150的包。假如您相信攻击者在50跳左
右,那么您可以对TTL的限制进行一下更改。
编译更改过的 ngrep
编译和安装都非常简单。您仅需要使用以下之一来取代ngrep.c 文件。处于方便起见,
我们可以详细说明。
这段代码只是在RedHat 6.1 和Mandrake 6.5 Linux上测试过。
首先您需要在 http://www.packetfactory.net/ngrep/ 下载ngrep,我们测试的是1.35
版。
然后在 ftp://ftp.ee.lbl.gov/libpcap.tar.Z下载libpcap 我们使用的是 0.40版。
把文件放在临时文件夹里并解包,
tar xvzf libpcap.tar.Z
然后进行编译
cd libpcap-0.4; ./configure; make; make install; make install-incl
假如您遇到了困难,可以参见在libpcap-0.4目录里的README或INSTALL文件。根据我们
实验的经验,如果/usr/local/include 和/usr/local/include/net目录在linux系统中
不存在的话,安装会失败。加入您在安装时遇到了pcap.h 或 bpf.h的错误时你可以运行
mkdir /usr/local/include; mkdir /usr/local/include/net然后重新运行'make inst
all-incl'。然后我们需要编译ngrep (使用我们修改过的版本)。首先解包
tar xvzf ngrep-1.35.tar.gz
然后进行配置
cd ngrep; ./configure
然后把ngrep.c复制到ngrep目录里。你可以覆盖也可以备份原始的ngrep.c文件。在这里
,您应当回顾在修改过的ngrep.c里的配置,至少您应当把DNS_SERVER_IP更改为您所使
用的DNS的地址。更改完毕后你就可以运行'make',这样就建立了ngrep应用程序。
Modified ngrep.c source code
/* this code is available for download from http://www.wiretrip.net/na/ngrep
.c */
/*
* $Id: ngrep.c,v 1.35 1999/10/13 16:44:16 jpr5 Exp $
*
*/
/* TFN detection code added by Rain Forest Puppy / rfp@wiretrip.net
and Night Axis / na@wiretrip.net */
/********* TFN detection defines *******************************/
/* how many DNS and ICMP requests to track */
#define DNS_REQUEST_MAX 5000
#define ICMP_REQUEST_MAX 1000
/* flood threshold is matches per 10 seconds */
#define FLOOD_THRESHOLD 20
/* IP of your DNS server */
#define DNS_SERVER_IP "10.9.100.8"
/* TFN syn uses ttl between 200-255. Assuming less than 50 hops,
flag stuff with ttl > TTL_THRESHOLD (other critera are used
as well) */
#define TTL_THRESHOLD 150
/**************************************************************/
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#ifdef LINUX
#include <getopt.h>
#endif
#if defined(BSD) || defined(SOLARIS)
#include <unistd.h>
#include <sys/types.h>
#include <ctype.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <net/if.h>
#endif
#if defined(LINUX) && !defined(HAVE_IF_ETHER_H)
h>
#include <pcap.h>
#include <net/bpf.h>
#include "regex.h"
#include "ngrep.h"
static char rcsver[] = "$Revision: 1.35 $";
int snaplen = 65535, promisc = 1, to = 1000;
int show_empty = 0, show_hex = 0, quiet = 0;
int match_after = 0, keep_matching = 0, invert_match = 0;
int matches = 0, max_matches = 0;
char pc_err[PCAP_ERRBUF_SIZE], *re_err;
int (*match_func)();
int re_match_word = 0, re_ignore_case = 0;
struct re_pattern_buffer pattern;
char *regex, *filter;
struct bpf_program pcapfilter;
struct in_addr net, mask;
char *dev = NULL;
int link_offset;
pcap_t *pd;
/**************** TFN2K detection **********************************/
unsigned int udp_flood_count=0, syn_flood_count=0;
unsigned int targa_flood_count=0, icmp_flood_count=0;
unsigned long my_dns, targ1, targ2, rfp1, icmp_flood=1;
time_t t;
unsigned long dns_circbuff[DNS_REQUEST_MAX];
unsigned int dns_cb_ptr=0;
unsigned long icmp_circbuff[ICMP_REQUEST_MAX];
unsigned int icmp_cb_ptr=0;
void add_dns (unsigned long ipadd){
dns_circbuff[dns_cb_ptr++]=ipadd;
if (dns_cb_ptr==DNS_REQUEST_MAX) dns_cb_ptr=0;}
void add_icmp (unsigned long ipadd){
icmp_circbuff[icmp_cb_ptr++]=ipadd;
if (icmp_cb_ptr==ICMP_REQUEST_MAX) dns_cb_ptr=0;}
void anti_tfn_init (void) {
unsigned int x;
for(x=0;x<DNS_REQUEST_MAX;x++) dns_circbuff[x]=0;
for(x=0;x<ICMP_REQUEST_MAX;x++) icmp_circbuff[x]=0;
my_dns=inet_addr(DNS_SERVER_IP);
printf("Ngrep with TFN detection modifications by wiretrip / www.wiretrip.ne
t\n");
printf("Watching DNS server: %s\n",inet_ntoa(my_dns));
targ1=htons(16383); targ2=htons(8192);
rfp1=htons(~(ICMP_ECHO << 8)); /* hopefull this is universal ;) */
alarm(20);}
void print_circbuffs (void) {
unsigned int x;
printf("Last (%u) DNS requests:\n",DNS_REQUEST_MAX);
for(x=0;x<DNS_REQUEST_MAX;x++)
if(dns_circbuff[x]>0) printf("%s\n",inet_ntoa(dns_circbuff[x]));
printf("\nLast (%u) ICMP echo requests (pings):\n",ICMP_REQUEST_MAX);
for(x=0;x<ICMP_REQUEST_MAX;x++)
if (icmp_circbuff[x]>0) printf("%s\n",inet_ntoa(icmp_circbuff[x]));}
void reset_counters (int sig) {
udp_flood_count=syn_flood_count=targa_flood_count=icmp_flood_count=0;
alarm(10);}
void tfn_attack_detected (char* attack_type){
if(icmp_flood==0) return;
(void)time(&t);
printf("\n%s",ctime(&t));
printf("A TFN2K %s attack has been detected!\n\n",attack_type);
print_circbuffs();
printf("\nIncoming realtime ICMP echo requests (pings):\n");
icmp_flood=0;}
/*********************************************************************/
int main(int argc, char **argv) {
char c;
signal(SIGINT,dealloc);
signal(SIGQUIT,dealloc);
signal(SIGABRT,dealloc);
signal(SIGPIPE,dealloc);
signal(SIGALRM,reset_counters);
anti_tfn_init();
while ((c = getopt(argc, argv, "d:")) != EOF) {
switch (c) {
case 'd':
dev = optarg;
break;}}
if (!dev)
if (!(dev = pcap_lookupdev(pc_err))) {
perror(pc_err);
exit(-1);}
if ((pd = pcap_open_live(dev, snaplen, promisc, to, pc_err)) == NULL) {
perror(pc_err);
exit(-1);}
if (pcap_lookupnet(dev,&net.s_addr,&mask.s_addr, pc_err) == -1) {
perror(pc_err);
exit(-1);}
printf("interface: %s (%s/", dev, inet_ntoa(net));
printf("%s)\n",inet_ntoa(mask));
switch(pcap_datalink(pd)) {
case DLT_EN10MB:
case DLT_IEEE802:
link_offset = ETHHDR_SIZE;
break;
case DLT_SLIP:
link_offset = SLIPHDR_SIZE;
break;
case DLT_PPP:
link_offset = PPPHDR_SIZE;
break;
case DLT_RAW:
link_offset = RAWHDR_SIZE;
break;
case DLT_NULL:
link_offset = LOOPHDR_SIZE;
break;
default:
fprintf(stderr,"fatal: unsupported interface type\n");
exit(-1);
} while (pcap_loop(pd,0,(pcap_handler)process,0));}
void process(u_char *data1, struct pcap_pkthdr* h, u_char *p) {
struct ip* ip_packet = (struct ip *)(p + link_offset);
switch (ip_packet->ip_p) {
case IPPROTO_TCP: {
struct tcphdr* tcp = (struct tcphdr *)(((char *)ip_packet) + ip_packet->ip_h
l*4);
if(tcp->th_flags==0x22 && ip_packet->ip_ttl > TTL_THRESHOLD){
if(++syn_flood_count > FLOOD_THRESHOLD) tfn_attack_detected("SYN");}
if(ip_packet->ip_ttl==0 &&
(ip_packet->ip_off==targ1 || ip_packet->ip_off==targ2)){
if(++targa_flood_count > FLOOD_THRESHOLD) tfn_attack_detected("TARGA");
}} break;
case IPPROTO_UDP: {
struct udphdr* udp = (struct udphdr *)(((char *)ip_packet) + ip_packet->ip_h
l*4);
#ifdef HAVE_DUMB_UDPHDR
if ((ntohs(udp->source) + ntohs(udp->dest)) == 65536) {
#else
if ((ntohs(udp->uh_sport) + ntohs(udp->uh_dport)) == 65536) {
#endif
if(++udp_flood_count > FLOOD_THRESHOLD) tfn_attack_detected("UDP");}
if(ip_packet->ip_dst.s_addr==my_dns &&
#ifdef HAVE_DUMB_UDPHDR
ntohs(udp->dest) == 53) {
#else
ntohs(udp->uh_dport) == 53) {
#endif
add_dns(ip_packet->ip_src.s_addr);
}} break;
icmp_cksum==rfp1 && ip_packet->ip_ttl==0){
if(++icmp_flood_count > FLOOD_THRESHOLD) tfn_attack_detected("ICMP");
} else { if(icmp_flood>0) add_icmp(ip_packet->ip_src.s_addr);
else printf("%s\n",inet_ntoa(ip_packet->ip_src));}}}}}
void dealloc(int sig) {
if (filter) free(filter);
exit(0);}
--
世界上有两件东西能够深深地震撼人们的心灵
一件是我们心中崇高的道德准则
另一件是我们头顶上灿烂的星空
——伊曼努尔·康德
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 172.16.3.205]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:208.983毫秒