谁在敲门:SYN拒绝服务攻击
在过去的几个月中,一种被称为“SYN攻击”的拒绝服务攻击变得臭名昭著。这种攻击可以阻止对您的邮件、WWW和其他关键服务器的访问。罗伯特·莫里斯在1985年的一篇论文中首次描述了这种攻击,但当时并未引起太多关注。直到2600杂志发布了利用TCP/IP协议栈流行实现中此漏洞的源代码后,这个漏洞才引起了互联网服务提供商的注意。纽约市的公共接入网络公司(Public Access Networks Corporation)是其中一家提供商,去年九月它多次遭到攻击,导致其邮件和Web服务器在很长一段时间内无法供用户使用。在本文中,我们将解释SYN到底是什么,为什么TCP/IP需要它,为什么这种攻击会奏效以及如何预防它。
互联网之所以能够良好运行,是因为其数据通信协议(IP、TCP和UDP)在十年间经历了重大修订和反复试验的“调整”而发展而来。因此,这些协议已经发展出传奇般的健壮性,使其难以被击败;然而,这些协议的设计基本假设是所有网络管理员都是值得信任的。不幸的是,在当今的互联网环境中,情况并非如此。如果掌握了正确的知识,几乎任何PC都可以被配置成让恶意个人(以系统或网络管理员的身份行事)能够搞垮互联网上的任何数量的服务器。
这些漏洞之一被称为“SYN”(同步)攻击,它会影响任何将服务器放置在互联网上的人。SYN攻击是一种拒绝服务攻击,阻止其他人连接到您的服务器。
互联网协议栈利用了OSI模型的三个主要层。最底层是物理层,它包含物理线路、网络主机适配器和适配器设备驱动程序。下一层是数据链路层,其工作是从网络上读取比特流,并将它们组装成帧,供更高的层使用。
互联网协议(IP)或网络层是下一层。它检查传入的帧,以确定它们是否是IP数据包,如果不是,则将帧传递给另一个协议栈(例如,Novell)或将帧作为无意义的数据丢弃。如果是IP数据包,则IP层会进一步评估数据包内容,以进行许多与IP相关的活动,例如地址解析协议(ARP)或互联网控制和消息协议(ICMP),无连接的 ping 和 traceroute 应用程序使用这些协议。
如果数据包不是上述格式之一,则会继续将其内容评估为传输控制协议(TCP)或用户数据报协议(UDP)数据包。如果数据包包含TCP标头,则会将其发布到更高的TCP层。“发布”这个动词意义重大,因为它表示数据包被移动到另一个地方进行处理,并且该处理将在未来的某个时间发生。换句话说,在IP-TCP边界,由中断驱动的信息从环境中“冒出来”;在IP-TCP边界,信息等待基于希望与网络通信的程序请求的处理。因此,IP-TCP边界包含固定数量的内存缓冲区,这些缓冲区分配给网络“活动”,而系统并不真正知道该活动是什么。SYN攻击正是在这个边界上起作用的。
在讨论第三个互联网层以及TCP如何建立连接之前,或许最好先从一个类比开始,来说明一个典型的网络问题以及TCP如何在日常工作中克服这个问题。
我们的类比从一个大学校园开始,一个勤奋的学生(SS)不幸地被安排住在一个“派对”宿舍。在一个典型的晚上,SS正在他的桌子上学习,试图掌握一些关于数据链路协议的枯燥材料,为他的计算机网络课程做准备。有人敲他的门。当他打开门时,他的吵闹的邻居向他扔了一个水球。SS运用他网络课程的知识,想出了一个解决方案来阻止他讨厌的邻居,但仍然可以迎接他邀请的访客。
他决定使用“秘密敲门”——他的朋友用一到五声敲门代码来宣告自己。SS听到敲门声后走到门口;然而,他并没有开门。相反,他重复了最初的敲门声,并加上了他自己的一到五声敲门代码。现在,访客敲击他的代码的下一个“序列”,并重复SS的敲门声。
这些敲门体操在数据通信术语中被称为三次握手(参见图1),解决了三个常见的网络问题。首先,它们允许两个主机建立起始“序列”号,接收方使用这些序列号来重新排序数据包或重新组装数据报。其次,它们使主机能够识别由于重传而产生的重复数据包,而重传又是延迟响应的结果。最后,如果任何一台计算机要在同一时间与第三台计算机建立连接,那么可以产生两个有序的连接,而不会造成混乱。
网络流量到达给定的主机,并在IP-TCP边界累积,但在用户级进程通过传输站(TCP或UDP)执行网络服务请求之前,什么都不会发生。
大多数用户级互联网应用程序使用“虚拟电路”模型与Web浏览器(如Netscape或Lynx)、FTP客户端和Telnet客户端进行通信。创建连接或虚拟电路的步骤需要远程计算机请求“连接”,这会将一个IP数据包放入本地计算机的IP-TCP边界缓冲区中。本地计算机程序请求“监听”,然后请求“接受”。正是在这些监听-连接-接受阶段,TCP使用三次握手来建立虚拟电路。
假设网络上有两个主机A和B。A希望连接到B,并发出连接请求。TCP数据报报头中定义了六个比特,其中两个是“SYN”(同步)和“ACK”(确认)比特。连接请求数据报的SYN比特被设置,而ACK比特被清除。当主机B上的进程接收到数据报时,它接受序列号,构建一个回复数据报,其中包含B的单独序列号加上主机A的序列号加一,并且数据报被发送到A,SYN和ACK比特都打开。主机A现在确认B已经临时接受了连接,并且它使用其第一个数据报的递增序列发送第一个数据,并返回B的递增序列号作为确认。现在数据报只设置了ACK比特,当主机B接收到它时,连接就建立了。(参见图2。)
回到上面的类比,我们可以看到敲门代码能够击退SS吵闹的邻居,但是如果他们决定每小时敲一次门或每五分钟敲一次门呢?我们的勤奋学生该怎么办?敲门声会分散他做作业的注意力,但如果他忽略敲门声,他就会错过任何来访的朋友。换句话说,频繁的敲门声会拒绝为SS的朋友提供服务。
IP-TCP边界缓冲区的情况也是如此。一旦主机接收到SYN数据报并回复ACK数据报,主机要等待三次握手的第三部分多久?不幸的是,当前的实现会永远等待。
在正常情况下,连接建立得很快,因此开发人员假设主机中所有可能的连接只需要少量缓冲区。在1.2.x Linux内核下,只分配了10个缓冲区。
要创建SYN攻击,程序不只是简单地使用连接请求;而是直接打开一个原始网络连接,并发送一连串TCP SYN数据报,忽略来自目标主机的任何回复。现在,这几个缓冲区已满,目标主机无法建立任何后续连接。对目标主机的服务已被拒绝。(参见图3。)
这种攻击如此阴险的原因在于,攻击者还在每个数据报中插入随机的IP源地址,从而使远程主机几乎不可能将数据报追溯到真实来源。
一家互联网服务提供商(ISP)关闭了一个用户的帐户,因为该用户违反了其可接受使用政策。现在,该用户在一家竞争对手的ISP处获得了帐户,并带着最新一期的2600杂志,使用运行Linux的PC拨号连接到新的ISP。该用户编译了2600中给出的示例程序,并针对其旧ISP的邮件服务器和Web服务器反复运行,填满了ISP服务器上的连接队列。没有人可以接收邮件或访问ISP的网页。
在多次重启其Web服务器后,ISP的一位管理员运行了 netstat,并注意到许多条目都被标记为SYN_RECV。所有这些条目都来自随机IP地址。管理员尝试ping几个地址,但它们都无法返回任何ping。然后,管理员致电其网络提供商,一家著名的国家服务提供商(NSP),并请求帮助追踪攻击的来源。不幸的是,NSP非常忙于维护其网络,并且没有资源来协助进行此类搜索。
这家ISP倒闭了。
为了减轻这种攻击的严重性,所有提供商都应安装适当的过滤器,以防止数据包离开其网络时带有伪造的源地址,这被称为IP欺骗。这可以通过阻止源地址来自您网络外部的数据包离开您的网络来完成。
由于Linux内核源代码是在GNU通用公共许可证(GPL)下发布的,因此任何拥有Linux副本的人都有权获得源代码。拥有源代码后,用户可以对其内核应用修复程序并重新编译它。如果您使用的是专有操作系统,那么您将受制于您的操作系统供应商。
解决此问题最简单的方法之一是增加队列的大小。这已经在2.0.x内核中完成。如果队列足够大,则连接速度较慢(拨号、动态IP连接)的主机更难发送足够的泛洪数据包来阻止正常连接。
为了使您的网络服务器能够利用更大的队列,必须使用更大的值重新编译它们,作为listen()函数的积压参数。Sendmail 和 inetd(在NetKit-B中找到)是两个必须重新编译以“SYN防范”您的系统的重要程序。
Alan Cox的一个补丁实现了随机丢弃未完成的连接,这可以防止缓冲区被填满,尽管监听队列中部分完成的连接数量可能会增加。截至补丁级别27,尚未集成到2.0.x内核中的同一补丁也禁止单个C类网络使用超过队列30%的资源。最后一种方法可以防止来自已安装上述源过滤器的提供商和不使用随机源地址的攻击者的攻击。
当前内核(2.0.29)的补丁可以从 http://www.dna.lth.se/~erics/linux.html 获取。要应用它,请下载补丁并将其解压缩到 /usr/src 子目录中,然后键入
patch < tcp-syncookies-patch-1。当您运行 make config(或 menuconfig 或 xconfig)时,您将在“网络选项”下看到两个新增项。只需将它们编译到内核中即可。
互联网论坛上已经提出了其他保护方法,包括创建防火墙,先建立TCP连接,然后再传递连接。几家公司正在基于这些想法销售商业产品。这些解决方案对于Linux用户来说不是必需的。诸如此类的网络解决方案适用于那些无法选择编译修复内核的用户。
Douglas L. Stewart 在Pencom Systems Administration工作,并于12月毕业于密西西比大学。可以通过电子邮件 douglas@pobox.com 联系 Douglas。
P. Tobin Maginnis 是密西西比大学计算机科学副教授。
Thomas Simpson 是密西西比大学计算机科学的研究生。