[摘要]本文主要讲述了tcp协议的功能、它的连接的建立与终止的过程,以及他本身安全问题上的缺陷和序列号攻击的防御措施。
[关键词]tcp协议 网络安全 协议攻击
一、tcp连接的建立与终止
1.概述
虽然tcp使用不可靠的ip服务,但它却提供一种可靠的运输层服务。
2.建立连接协议(三次“握手”)
(1)客户端发送一个带syn标志的tcp报文到服务器。这是三次握手过程中的报文1.
(2)服务器端回应客户端的,这是三次握手中的第2个报文,这个报文同时带ack标志和syn标志。因此它表示对刚才客户端syn报文的回应;同时又标志syn给客户端,询问客户端是否准备好进行数据通讯。
(3)客户必须再次回应服务段一个ack报文,这是报文段。
3.连接终止协议(四次握手)
由于tcp连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个fin来终止这个方向的连接。收到一个 fin只意味着这一方向上没有数据流动,一个tcp连接在收到一个fin后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
(1)tcp客户端发送一个fin,用来关闭客户到服务器的数据传送(报文段4)。
(2)服务器收到这个fin,它发回一个ack,确认序号为收到的序号加1(报文段5)。和syn一样,一个fin将占用一个序号。
(3)服务器关闭客户端的连接,发送一个fin给客户端(报文段6)。
(4)客户段发回ack报文确认,并将确认序号设置为收到序号加1(报文段7)。
closed:表示初始状态。
listen:表示服务器端的某个socket处于监听状态,可以接受连接了。
syn_rcvd:这个状态表示接受到了syn报文,在正常情况下,这个状态是服务器端的socket在建立tcp连接时的三次握手会话过程中的一个中间状态,很短暂,基本上用netstat你是很难看到这种状态的,因此这种状态时,当收到客户端的ack报文后,它会进入到established状态。
syn_sent:这个状态与syn_rcvd遥相呼应,当客户端socket执行connect连接时,它首先发送syn报文,因此也随即它会进入到了syn_sent状态,并等待服务端的发送三次握手中的第2个报文。syn_sent状态表示客户端已发送syn报文。
established:表示连接已经建立了。
fin_wait_1:fin_wait_1和fin_wait_2状态的真正含义都是表示等待对方的fin报文。而这两种状态的区别是:fin_wait_1状态实际上是当socket在established状态时,它想主动关闭连接,向对方发送了fin报文,此时该socket即进入到fin_wait_1状态。而当对方回应ack报文后,则进入到fin_wait_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ack报文,所以fin_wait_1状态一般是比较难见到的,而fin_wait_2状态还有时常常可以用netstat看到。
fin_wait_2:上面已经详细解释了这种状态,实际上fin_wait_2状态下的socket,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。
time_wait:表示收到了对方的fin报文,并发送出了ack报文,就等2msl后即可回到closed可用状态了。如果fin_wait_1状态下,收到了对方同时带fin标志和ack标志的报文时,可以直接进入到time_wait状态,而无须经过fin_wait_2状态。
closing:这种状态比较特殊,属于一种比较罕见的例外状态。正常情况下,当你发送fin报文后,按理来说是应该先收到(或同时收到)对方的ack报文,再收到对方的fin报文。但是closing状态表示你发送fin报文后,并没有收到对方的ack报文,反而却也收到了对方的fin报文。什么情况下会出现此种情况呢?那就是如果双方几乎在同时close一个socket的话,那么就出现了双方同时发送fin报文的情况,也即会出现closing状态,表示双方都正在关闭socket连接。
close_wait:这种状态的含义表示在等待关闭。怎么理解呢?当对方close一个socket后发送fin报文给自己,你系统毫无疑问地会回应一个ack报文给对方,此时则进入到close_wait状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以close这个socket,发送fin报文给对方,也即关闭连接。所以你在close_wait状态下,需要完成的事情是等待你去关闭连接。
last_ack:这个状态是被动关闭一方在发送fin报文后,最后等待对方的ack报文。当收到ack报文后,也即可以进入到closed可用状态了。
二、tcp协议安全问题
1.概述
tcp协议现在用得非常广泛,但它本身也有一些安全上的缺陷。一些缺陷是由于主机使用ip源地址作为认证机制引起的;berkeley的r系列涮用就是一个明显的例子。其它的一些缺陷是由于网络控制机制,特别是路由协议,缺少认证机制引起的。
序列号预测攻击
tcp序列号预测攻击最早是1985年由对这一安全漏洞进行阐述的。他使用tcp序列号预测,即使是没有从服务器得到任何响应,来产生一个tcp包序列。这使他能欺骗在本地网络上的主机。
(1)攻击方法。tcp协议有一个非常令人着迷的漏洞,简单的说,就是通过预测初始序列号来伪造tcp包.并且不需要得到回应。这样就可以使攻击者伪装成一台和服务器在同一个局域网上的一台可信任的机器。通常建立tcp连接需要三次握手。客户机送一个初始序列号isnc,服务器应答它并送出它自己的序列号isns,客户机再发出一个应答包。这三个数据包发送以后,就可以传输数据了。这个过程可以用下图来表示:
c一>s:syn(isnc)
s一>c:syn(isns),ack(isnc)
c一>s:ack(isns)
c一>s:data
and/or
s一>c:data
这就是说,要使一个连接建立起来,c必须知道isns,这个数多少有一些随机性,假没入侵者x有一种方法可以预测isns。在这种情况下,他可以通过以下的步骤来模仿可信任的主机t:
x->s:syn(isnx),src=t
s->t:syn(isns),ack(isnx)
x一>s:ackfisns),src=t
x一>s:ack(isns),src=t,nasty-data
即使s一>t的数据包不经过x,x也能知道它的内容,因此能发送数据。如果x在一个能够执行命令的连接上实行这种攻击(例如berkeley rsh服务),他就可以运行——恶意的命令。那么怎样预测随机的isn 呢?在berkeley系统中,初始序列号变量是以每秒固定的数目递增的,而每次连接的序列号就是这个变量的一半。因此,如果有人通过合法的连接观察isns,他就有很大的机会通过计算得到下一次连接的isns。
应该指出的是服务器的应答消息s一>t:syn(isns),ack(isnx)。并没有消除这种攻击;虽然真正的t主机将接收到它,并且会重设连接。这并不是一个严重的障碍,因为我们可以通过一些拒绝服务的攻击使t主机暂时失效,也可以在t主机关机或重起的时候攻击。还有一种通过netstat服务对tcp序列号进行的攻击。在这种攻击中,入侵者模仿一台关闭的主机。如果在目标机上有netstat服务.它就会提供另一个端口必要的序列号信息:这样就根本不需要猜测了。
(2)防御。很明显,这种攻击的关键是berkeley系统中初始序列号变量变化方式太简单了。tcp标准要求这个变量必须以每秒钟将近250,000的速度增长:berkerey系统则使用了一个比它慢得多的速度然而关键的因素是间隔的大小而不是平均速度。从4.2bsd系统的每秒增加128到4.3bsd 的每秒增加125,000的改变是没有意义的。下面让我们来看看以250,000的频率运行是否有用。为了简单起见,现忽略了其它连接产生的问题,仅仅考虑本计数器固定速度的改变:为了知道当前的序列号,必须发送一个syn包,并接收它的回应。如下:
x一>s:synfisnx1
s一>x:syn(isns),ack(isnx)(1)
第一个使服务器产生下一序列号的伪造的数据包,可以紧跟在服务器对探测包的回应后送出:
x一>s:syn(isnx),src=t (2)
序列号isns在应答中使用
s一>t:syn(isns),ack(isnx)
它是由数据包(1)产生到服务器接收到数据包(1)之间的时间唯一确定的。但是这个时间是由x到s的来回时间确定的。因此如果攻击者能够测量或预测到这个时间。即使使用一个能精确的4微秒的时钟也不能阻止这种攻击。对来回时间的测量能精确到什么程度呢?如果假设网络很稳定,我们可以精确到10毫秒左右。很明显,互联网不可能长期这么稳定.但是却有可能在一个较短的时间内稳定。因此我们有2500个isns的可能值。考虑到重新测量来回时间所需的时间,我们假设每次尝试需要花5秒,那么一个攻击者很可能在7500秒内获得成功。条件更好的网络或更精确的测量,能够提高成功的可能性。因此,仅仅是按tcp协议标准是不行的。在这里,我们默认的假设是目标机上不运行任何进程。实际上,当新的请求到达时,是会运行一些进程的。在一个6mips的机器上,一个时钟周期-4秒大约可执行25条指令。高优先级的中断tcb分配顺序的不同,都对下一个序列号有相当大影响。这种随机的效果是被认为是主机的优点。
参考文献:
[1]于万国,陈日升.计算机网路安全与防范[j].中国教育科研与探索,2007,(5).