webhero 2015-03-30
1.RST标识位
RST表示复位,用来异常的关闭连接,在TCP的设计中它是不可或缺的。发送RST包关闭连接时,不必等缓冲区的包都发出去(FIN包),直接就丢弃缓存区的包发送RST包。而接收端收到RST包后,也不必发送ACK包来确认。
TCP处理程序会在自己认为的异常时刻发送RST包。
2个例子:
1)A向B发起连接,但B之上并未监听相应的端口,这时B操作系统上的TCP处理程序会发RST包。
2)A和B已经正常建立连接,正在通讯时,A向B发送了FIN包要求关连接,B发送ACK后,A网断了,A通过若干原因放弃了这个连接(例如进程重启)。网络恢复之后,B又开始或重发数据包,A不知道这连接哪来的,就发了个RST包强制把连接关闭,B收到后会出现connect reset by peer错误。
2.RST复位报文段
TCP在下列三种情况下产生RST复位报文段。
1.到不存在的端口的连接请求
产生复位的一种常见情况是当连接请求到达时,目的端口没有进程正在监听。对于UDP,当一个数据报到达目的端口时,该端口没在使用,它将产生一个ICMP端口不可达的信息;而TCP则使用复位。
2.异常终止一个连接
终止一个连接的正常方式是一方发送FIN,这也称为有序释放,因为在所有排队数据都已发送之后才发送FIN,正常情况下没有任何数据丢失。但也有可能发送一个复位报文段而不是FIN来中途释放一个连接,这也称为异常释放。异常终止一个连接对应用程序来说有两个优点:(1)丢弃任何待发数据并立即发送复位报文段;(2)RST的接收方会区分另一端执行的是异常关闭还是正常关闭。
3.检测半关闭连接
如果一方已经关闭或异常终止连接而另一方却还不知道,我们将这样的TCP连接称为半打开的。任何一端的主机异常都可能导致发生这种情况。只要不打算在半打开连接上传输数据,仍处于连接状态的一方就不会检测另一方已经出现异常。下面介绍一种建立半打开连接的情形。在bsdi上运行Telnet客户程序,通过它和svr4上的丢弃服务器建立连接。接着断开服务器主机与以太网的电缆,并重启服务器主机。这可以模拟服务器主机出现异常(在重启服务器之前断开以太网电缆是为了防止它向打开的连接发送FIN,某些TCP在关机时会这么做)。服务器主机重启后,我们重新接上电缆,并从客户向服务器发送一行字符。由于服务器的TCP已经重新启动,它将丢失复位前连接的所有信息,因此它不知道数据报文段中提到的连接。TCP处理的原则是接收方以复位作为应答。
3.RST复位攻击
A和服务器B之间建立了TCP连接,如果此时C伪造了一个TCP包发给B,使B异常的断开了与A之间的TCP连接,就是RST攻击。
伪造这样的TCP包能造成什么后果?
1、假定C伪装成A发过去的包,这个包如果是RST包,冲区上所有数据B将会丢弃与A的缓,强制关掉连接。
2、如果发过去的包是SYN包,那么,B会表示A已经是正常连接却又来建新连接,B主动向A发个RST包,并在自己这端强制关掉连接。
如何伪造成A发给B的包?
这里有两个关键因素,源端口和序列号。
一个TCP连接都是四元组,由源IP、源端口、目标IP、目标端口唯一确定一个连接。所以,如果C要伪造A发给B的包,要在上面提到的IP头和TCP头,把源IP、源端口、目标IP、目标端口都填对。
1)这里B作为服务器,IP和端口是公开的;
2)A是我们要下手的目标,IP当然知道,但A的源端口就不清楚了,因为这可能是A随机生成的。当然,如果能够对常见的OS如windows和linux找出生成source port规律的话,还是可以进行碰撞。
3)序列号问题是与滑动窗口对应的,伪造的TCP包里需要填序列号,如果序列号的值不在A之前向B发送时B的滑动窗口内,B是会主动丢弃的。所以我们要找到能落到当时的AB间滑动窗口的序列号。这个可以暴力解决,因为一个sequence长度是32位,取值范围0-4294967296,如果窗口大小像上图中我抓到的windows下的65535的话,只需要相除,就知道最多只需要发65537(4294967296/65535=65537)个包就能有一个序列号落到滑动窗口内。RST包是很小,IP头+TCP头才40字节,算算我们的带宽就知道这实在只需要几秒钟就能搞定。
那么,序列号不是问题,源端口会麻烦点,如果各个操作系统不能完全随机的生成源端口,或者黑客们能通过其他方式获取到source port,RST攻击存在可能。