TCP状态

TCP连接状态,SYNC_RECV,CLOSE_WAIT,TIME_WAIT_服务器

时序图

TCP连接状态,SYNC_RECV,CLOSE_WAIT,TIME_WAIT_服务器_02

ACK

TCP连接状态,SYNC_RECV,CLOSE_WAIT,TIME_WAIT_半连接_03

TCP数据包中的序列号(Sequence Number)不是以报文段来进行编号的,而是将连接生存周期内传输的所有数据当作一个字节流,序列号就是整个字节流中每个字节的编号

一个TCP数据包中包含多个字节流的数据(即数据段),而且每个TCP数据包中的数据大小不一定相同

在建立TCP连接的三次握手过程中,通信双方各自已确定了初始的序号x和y,TCP每次传送的报文段中的序号字段值表示所要传送本报文中的第一个字节的序号

TCP的报文到达确认(ACK),是对接收到的数据的最高序列号的确认,并向发送端返回一个下次接收时期望的TCP数据包的序列号(Ack Number)

例如,主机A发送的当前数据序号是400,数据长度是100,则接收端收到后会返回一个确认号是501的确认号给主机A

TCP提供的确认机制,可以在通信过程中可以不对每一个TCP数据包发出单独的确认包(Delayed ACK机制),而是在传送数据时,顺便把确认信息传出

这样可以大大提高网络的利用率和传输效率

同时,TCP的确认机制,也可以一次确认多个数据报,例如,接收方收到了201,301,401的数据报,则只需要对401的数据包进行确认即可

对401的数据包的确认也意味着401之前的所有数据包都已经确认,这样也可以提高系统的效率

SYN_RECV 

服务端收到建立连接的SYN没有收到ACK包的时候处在SYN_RECV状态

net.ipv4.tcp_synack_retries :INTEGER

  • 默认值是5

对于远端的连接请求SYN,内核会发送SYN + ACK数据报,以确认收到上一个SYN连接请求包

这是所谓的三次握手( threeway handshake)机制的第二个步骤

  • 这里决定内核在放弃连接之前所送出的 SYN+ACK 数目,不应该大于255,默认值是5,对应于180秒左右时间
  • 通常我们不对这个值进行修改,因为我们希望TCP连接不要因为偶尔的丢包而无法建立

net.ipv4.tcp_syncookies

一般服务器都会设置net.ipv4.tcp_syncookies=1来防止SYN Flood攻击

  • 假设一个用户向服务器发送了SYN报文后突然死机或掉线,那么服务器在发出SYN+ACK应答报文后是无法收到客户端的ACK报文的(第三次握手无法完成)
  • 这种情况下服务器端一般会重试(再次发送SYN+ACK给客户端)并等待一段时间后丢弃这个未完成的连接
  • 这段时间的长度我们称为SYN Timeout,一般来说这个时间是分钟的数量级(大约为30秒-2分钟)

SYN Flood攻击

  • 这些处在SYNC_RECV的TCP连接称为半连接
  • 并储在内核的半连接队列中,在内核收到对端发送的ack包时会查找半连接队列
  • 并将符合的requst_sock信息存储到完成三次握手的连接的队列中,然后删除此半连接
  • 大量SYNC_RECV的TCP连接会导致半连接队列溢出,后续的连接建立请求会被内核直接丢弃

能够有效防范SYN Flood攻击的手段之一,就是SYN Cookie

SYN Cookie是对TCP服务器端的三次握手协议作一些修改,专门用来防范SYN Flood攻击的一种手段

原理

  • 在TCP服务器收到TCP SYN包并返回TCP SYN+ACK包时,不分配一个专门的数据区,而是根据这个SYN包计算出一个cookie值
  • 在收到TCP ACK包时,TCP服务器在根据那个cookie值检查这个TCP ACK包的合法性
  • 如果合法,再分配专门的数据区进行处理未来的TCP连接


例如观测服务上SYN_RECV连接个数为:7314,对于一个高并发连接的通讯服务器,这个数字比较正常



CLOSE_WAIT

发起TCP连接关闭的一方称为client,被动关闭的一方称为server

  • 被动关闭的server收到FIN后,但未发出ACK的TCP状态是CLOSE_WAIT
  • 出现这种状况一般都是由于server端代码的问题,如果你的服务器上出现大量CLOSE_WAIT,应该要考虑检查代码

TIME_WAIT

根据TCP协议定义的3次握手断开连接规定,发起socket主动关闭的一方,socket将进入TIME_WAIT状态

  • TIME_WAIT状态将持续2个MSL(Max Segment Lifetime),在Windows下默认为4分钟,即240秒
  • TIME_WAIT状态下的socket不能被回收使用

现实场景

  • 对于一个处理大量短连接的服务器,如果是由服务器主动关闭客户端的连接,将导致服务器端存在大量的TIME_WAIT状态的socket
  • 甚至比处于Established状态下的socket多的多,严重影响服务器的处理能力,甚至耗尽可用的socket,停止服务

为什么需要TIME_WAIT?

  • TIME_WAIT是TCP协议用以保证被重新分配的socket不会受到之前残留的延迟重发报文影响的机制的必要逻辑保证

TIME_WAIT状态有关的系统参数有一般由3个

  • net.ipv4.tcp_tw_recycle = 1
  • net.ipv4.tcp_tw_reuse = 1
  • net.ipv4.tcp_fin_timeout = 30

net.ipv4.tcp_fin_timeout,默认60s,减小fin_timeout,减少TIME_WAIT连接数量

net.ipv4.tcp_tw_reuse = 1表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭

net.ipv4.tcp_tw_recycle = 1表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭

论读书


睁开眼,书在面前 闭上眼,书在心里