在TCP的三次握手中,客户端发送SYN(同步)数据包给服务器,服务器收到SYN后会回复一个SYN/ACK(同步/确认)数据包给客户端,客户端再回复一个ACK(确认)数据包给服务器。在这个过程中,服务器维护了两个队列:半连接队列和全连接队列:
- 半连接队列,也叫未完成连接队列,简称为syn队列
- 全连接队列,也叫已完成连接队列,简称为accept队列
- 什么是半连接队列和全连接队列
半连接队列: 半连接队列是指服务器在收到客户端的SYN请求,但还没有完整建立连接时所处的状态。当服务器收到客户端的SYN请求后,将客户端的请求放入半连接队列,等待服务器完成第二次握手并建立连接。在半连接队列中,服务器可以接受新的SYN请求,但是尚未完成三次握手的连接不会被传递给应用程序处理。
全连接队列: 全连接队列是指服务器在完成三次握手后,建立起完整的连接并已被应用程序接受的连接所处的状态。当服务器完成三次握手并建立连接后,将连接从半连接队列移动到全连接队列中。在全连接队列中,连接已经建立,可以进行数据的传输和处理。
- 半连接队列和全连接队列的作用
半连接队列:
- 提供临时存储空间:半连接队列为尚未完成三次握手的连接提供了临时存储空间,保留了连接的基本信息。
- 防止连接丢失:当服务器的并发连接请求超过其处理能力时,半连接队列可以暂存未完成握手的连接,避免连接请求被丢失。
全连接队列:
- 存储已建立连接:全连接队列存储已经完成三次握手并建立连接的请求。
- 提供应用程序访问接口:应用程序可以从全连接队列中获取连接,并进行数据的传输和处理。
- 管理连接资源:全连接队列可以帮助服务器管理连接资源,确保连接的正常建立和稳定传输。
需要注意的是,半连接队列和全连接队列都有一定的容量限制。当队列已满时,新的连接请求可能会被服务器拒绝或忽略。这种情况下,客户端一般会收到连接超时或连接被拒绝的错误信息。
- 如何防御SYN攻击
SYN攻击是一种常见的网络攻击方式,攻击者对服务端一直发送 TCP SYN 包,但是不回第三次握手 ACK,这样就会使得服务端有大量的处于SYN_RECV状态的 TCP 连接。这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。
增大半连接队列:由于是大量的SYN请求导致未连接队列被塞满,使正常的TCP连接无法顺利完成三次握手,通过增大半连接队列空间可以缓解这种压力。
开启 tcp_syncookies 功能:开启tcp_syncookies ,服务端将客户端SYN报文中的一些信息保存在了序号中,就不需要保留此连接的request_sock结构了,在发送完SYN+ACK报文之后,将已经申请的资源释放,降低SYN攻击时的资源消耗。
减少syn+ack报文的重传次数:因为我们在收到syn攻击时,服务端会重传syn+ack报文到最大次数,才会断开连接。针对syn攻击的场景,我们可以减少ack+syn报文的重传次数,使处于syn_recv状态的它们更快断开连接