等待2MSL的意义
如果不等待会怎样?
如果不等待,客户端直接跑路,当服务端还有很多数据包要给客户端发,且还在路上的时候,若客户端的端口此时刚好被新的应用占用,那么就接收到了无用数据包,造成数据包混乱。所以,最保险的做法是等服务器发来的数据包都死翘翘再启动新的应用。
那,照这样说一个 MSL 不就不够了吗,为什么要等待 2 MSL?
-
1 个 MSL 确保四次挥手中主动关闭方最后的 ACK 报文最终能达到对端
-
1 个 MSL 确保对端没有收到 ACK 重传的 FIN 报文可以到达
这就是等待 2MSL 的意义。
为什么是四次挥手而不是三次?
因为服务端在接收到FIN
, 往往不会立即返回FIN
, 必须等到服务端所有的报文都发送完毕了,才能发FIN
。因此先发一个ACK
表示已经收到客户端的FIN
,延迟一段时间才发FIN
。这就造成了四次挥手。
如果是三次挥手会有什么问题?
等于说服务端将ACK
和FIN
的发送合并为一次挥手,这个时候长时间的延迟可能会导致客户端误以为FIN
没有到达客户端,从而让客户端不断的重发FIN
。
同时关闭会怎样?
如果客户端和服务端同时发送 FIN ,状态会如何变化?如图所示:
004: 说说半连接队列和 SYN Flood 攻击的关系
三次握手前,服务端的状态从CLOSED
变为LISTEN
, 同时在内部创建了两个队列:半连接队列和全连接队列,即SYN队列和ACCEPT队列。
半连接队列
当客户端发送SYN
到服务端,服务端收到以后回复ACK
和SYN
,状态由LISTEN
变为SYN_RCVD
,此时这个连接就被推入了SYN队列,也就是半连接队列。
全连接队列
当客户端返回ACK
, 服务端接收后,三次握手完成。这个时候连接等待被具体的应用取走,在被取走之前,它会被推入另外一个 TCP 维护的队列,也就是全连接队列(Accept Queue)。
SYN Flood 攻击原理
SYN Flood 属于典型的 DoS/DDoS 攻击。其攻击的原理很简单,就是用客户端在短时间内伪造大量不存在的 IP 地址,并向服务端疯狂发送SYN
。对于服务端而言,会产生两个危险的后果:
-
处理大量的
SYN
包并返回对应ACK
, 势必有大量连接处于SYN_RCVD
状态,从而占满整个半连接队列,无法处理正常的请求。 -
由于是不存在的 IP,服务端长时间收不到客户端的
ACK
,会导致服务端不断重发数据,直到耗尽服务端的资源。
如何应对 SYN Flood 攻击?
-
增加 SYN 连接,也就是增加半连接队列的容量。
-
减少 SYN + ACK 重试次数,避免大量的超时重发。
-
利用 SYN Cookie 技术,在服务端接收到
SYN
后不立即分配连接资源,而是根据这个SYN
计算出一个Cookie,连同第二次握手回复给客户端,在客户端回复ACK
的时候带上这个Cookie
值,服务端验证 Cookie 合法之后才分配连接资源。