TCP系列09—链接管理—八、TCP Reset

        咱们在介绍TCP头的时候,提到过其中有个RST标志位。当一个TCP报文中这个标志位打开的时候,咱们叫作reset包(严格的说应该叫作reset段,可是不少时候段包帧并不加以区分)或者简单称呼为reset、RST。一般reset的产生是因为一个异常包致使,reset通常会致使TCP链接的快速断开。产生reset的几种常见的情形以下linux

  1. 向一个未打开的端口发送链接请求缓存

  2. 应用程序主动终止一个链接sass

  3. 应用程序尚未接收缓存中的数据,链接被提早关闭socket

  4. TWA(TIME-WAIT Assassination)
    tcp

  5. 半开链接的状况下发送数据spa

注意咱们这里是描述的reset产生的一些场景(并且是部分场景),在具体reset的产生缘由上可能会有重复,好比第一、四、5均可以认为是对端没有打开相对应的TCP端口。3d


1、向一个未打开的端口发送链接请求orm

        reset产生的一个常见的缘由是,在一个未打开的端口发送链接请求。这里未打开的端口是指没有应用程序在监听这个端口等待链接。server

以下图wireshark抓包,再不开启server状况下,没有应用程序监听9877端口,当client链接9877端口的时候就会产生reset消息。

注意我截图中的系列号,在这个截图中我设置了wireshark显示绝对系列号(前面文章截图显示的都是相对系列号),由于SYN包中的ACK标志没有置位,ack number字段无效(实际是以0填充的),因此在reset中的seq=0,ack则为SYN包中的seq+1(由于SYN标志和FIN标志在逻辑上占1byte)。一个reset包若是要被TCP endpoint接收,ACK标志必须置位且ack number落在有效的窗口区间内(窗口相关知识后面细讲)。这帮助阻止了一个简单的reset攻击(RFC5961),不然攻击者能够经过伪造源IP地址、源端口号构造一个reset消息来中断TCP链接。blog

2、应用程序主动经过reset消息终止一个链接

        应用程序能够经过socket API接口设置主动reset一个TCP链接,这种状况下的链接中断过程称为abortive release。以前咱们介绍过的四次挥手之类的经过FIN终止链接的过程咱们称呼为orderly release。在abortive release状况下,reset包的发送端缓存的待发送数据都会直接丢弃,接收端接收到reset后也能够知道是对端主动abort了这个tcp链接。

        wireshark截图以下,注意client发送reset后,并不会引发server回应ACK之类的消息。

能够看到RST消息的seq正好是对端指望接收的seq,按照RFC5961要求,非SYN_SENT状态下,接收端须要判断RST消息的系列号seq为正好为本身指望接收的seq,才会认为这个RST消息有效。若是RST的系列号seq落在接收窗口内但不是指望的seq时候,接收端须要发送challenge ACK,若是落在接收窗口外则会直接丢弃这个RST消息。(实际上challenge ACK也会引发RST,详见RFC5961,此处不作介绍。)

3、应用层尚未读取完接收缓存中的数据,链接被提早关闭

       当TCP接收端缓存中还有缓存数据而没有被应用层接收,可是应用层直接关闭TCP链接时候就会产生reset,以下图wireshark抓包所示,链接创建后client向server发送10bytes的数据,server应用层并无读取这10bytes的数据而是直接关闭tcp链接就会产生reset。

4、TWA(TIME-WAIT Assassination)

        TCP在TIME-WAIT状态下的时候,若是接收到reset包,它可能会提早结束TIME-WAIT状态,这种行为即叫作TIME-WAIT Assassination(TWA),数据包的流程以下图所示

为了不TIME-WAIT状态提早被reset结束,一些系统的TCP实如今TIME-WAIT状态下不会响应rst消息。linux则能够经过net.ipv4.tcp_rfc1337设置TCP在TIME-WAIT下是否响应reset,若是设置tcp_rfc1337为0,在TIME-WAIT下若是接收到reset则会直接关闭tcp链接,而不会等到2MSL超时。

5、半开链接的状况下发送数据

        关于半开链接咱们前面已经进行了介绍,同时wireshark抓包中也有对应的reset的展现,此处再也不介绍。















相关文章
相关标签/搜索