目录
三次握手
文字描述三次握手过程
为什么是三次握手?
什么是SYN洪水?
连接和半连接队列
一次、两次握手行不行,四/五/六次握手行不行?
三次握手一定会成功吗?
三次握手的过程中可不可以携带数据
TCP中的ISN能不能固定
四次挥手
四次挥手文字描述
四次挥手客户端和服务端的状态变换
挥手为什么需要四次
四次挥手释放连接时,为什么要等待2MSL
TIME_WAIT和CLOSE_WAIT
TIME_WAIT会引起bind失败的问题
编辑 服务器上大量出现close_wait是的原因
感性理解:
小红:我有东西要给你,我们建立连接吧。(第一次握手)
小蓝:OK,我准备好了。(第二次握手)
小红:谢谢你受理我的请求。(第三次握手)
知识准备:
1.tcp报文是有类型的。根据类型不同做不同的动作。上图握手过程中标注的如ACK,SEQ等都是报头中的字段,实际上发送时是将上图中的标志位或字段进行处理再发送完整的报文,不要只关注表面的ACK......这些字眼。
2.三次握手并不是一定会成功。
3.连接建立后是要被OS管理起来的(先描述,在组织),维护一个连接是有成本的。
4.ACK:确认号是否有效。SYN:请求建立连接; 我们把携带SYN标识的称为同步报文段。SEQ表示序号,ACK_SEQ表示确认序号。
握手过程
文字描述部分以上图为例:
第一次握手,客户端向服务器发送连接请求,报头中SYN标志位设置为1,序号为X。此时客户端的状态是【SYN_SENT】
第二次握手,服务端收到客户端的SYN后,向客户端发送ACK+SYN,将报头中的ACK和SYN标志位设置为1,确认序号为X+1,序号设为Y。服务端的的状态是【SYN_RCVD】,客户端收到确认后先建立连接,状态变为【ESTABUSHED】
第三次握手,客户端向服务端发送确认,将报头中的ACK设置为1,确认序号为Y+1,序号为X+1。服务端收到确认后,状态变为【ESTABUSHED】
原因1:三次握手以最低成本验证了双方通信信道的通畅,保证通信双反既能发消息,也能收消息。验证过程如下:
第一次握手,服务端收到客户端发来的报文后,服务端知道【客户端的发送能力和服务端的接收能力是没问题的】。
第二次握手,客户端收到了服务端的ACK和SYN,客户端知道【客户端的发送和接收能力,服务端的接收和发送都是没问题的】。注意:服务端此时还不能确认客户端的接收能力,需要等收到应答后才能确定。
第三次握手,服务端收到了来自客户端的应答,此时服务端知道【客户端的接收和发送能力,服务端的发送和接收能力都是没问题的】。
原因2:在三次握手的过程中,是客户端先建立了连接,服务端才建立连接。这就有效预防了单机攻击服务器的情况,没有明显的漏洞。这就好比你的朋友叫你吃辣根,你和他说:“你先吃,你吃了我就吃”。此时,你的朋友如果想要恶搞你,就要先尝到辣根的刺激。
SYN攻击就是客户端在短时间内,不断的向服务端发送SYN包,服务端收到SYN后回复确认包并等待客户端确认。这些SYN包长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。
服务器第一次收到客户单发来的SYN后处于SYN_RCVD状态,此时双方还没有完全建立连接。服务器会把这种状态下的请求连接放在队列中,这个队列称为半连接队列。
三次握手完成后,会发完全建立的连接放到全连接队列中。
不行,原因如下:
1.一次/二次握手不行,不知道双方的通信信道是否通畅。有明显的漏洞,抵不住单机SYN洪水攻击。
2.四/五/六次握手按照理论上来讲是没问题的,既然三次握手就已经能验证双方的通信信道是否通畅了,多次握手也一定能验证。但是这无非是单纯的在浪费资源,花100块就能解决的问题,为什么要花200呢?而且对于偶数次的握手而言,是服务端先建立的连接,这是有明显漏洞的。
3.需要注意的是,即使是三次握手,客户端先建立连接。也不能完全的避免攻击问题,但是这本来就不是建立握手要解决的问题。
不一定。
1.我们认为,只有收到了应答,才确认历史消息是被收到的,是可靠的。
2.总有最新的消息没有应答,,对于第三次握手来说,就是最新的消息,不能保证可靠性。
3.如果第三次握手丢失了,客户端和服务端的反应如下:
服务端
第三次握手丢失后,根据超时重传机制重新发送SYN+ACK,如果重发指定次数后,仍然没有收到客户端的应答,一段时间后,服务端自动关闭这个连接。
客户端
对于客户端而言,第三次握手的ACK发出后,客户端认为已经建立了连接,此时如果向服务端发送消息,服务端会返回一个RST设置为1的包,此时会重新向服务端建立连接。如果客户端收到了服务端发送的SYN+ACk,客户端会从新发送ACK.
第一次、第二次握手不可以携带数据,如果有人要攻击服务器,在第一次握手中携带大量的数据,并疯狂的发送SYN报文,这会让服务器花费很多的时间,空间来接收报文。简单的说就是容易让服务器受到攻击。
第三次握手的时候可以携带数据,此时的客户端已经处于连接状态了,这时的客户端已经知晓了服务端的接收和发送能力是否正常,所以携带数据是OK的。
不能,原因如下:
1.TCP初始化序号设置为一个固定值,这样会容易被攻击者猜测到后续的序号,从而遭到攻击。
2.假设服务端和客户端由于某种原因不停的断开和重连,那么之前交互的报文很可能在连接断开后没有到达服务端,而是在新连接建立后到达服务端,如果ISN是固定的,就可能会出现两次连接希望收到的序列号是相同的。
感性理解:
小蓝:我要删除你的联系方式,不在联系。
小红:好的
小红:我也要删除你的联系方式,此后不在联系。
小蓝:OK
知识准备:
1.对于接下来要描述的四次挥手,所谓的不再发送数据,指的是不发用户数据,在底层还是要对报文的交互进行管理。
2.FIN:通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段。RST: 对方要求重新建立连接; 我们把携带RST标识的称为复位报文段。
1.第一次挥手,客户端向服务端发送FIN设置为1的报文,想要断开连接。
2.第二次挥手,服务端收到FIN后,向客户端发送ACk设置为1的确认,同意断开连接。
3.第三次挥手,服务端向客户端发送FIN设置为1的报文,请求断开连接。
4.第四次挥手,客户端向服务端发送ACk设置为1的确认报文,同意断开连接。
1.客户端和服务端都要分别释放连接。
2.TCP是全双工的模式:
当小蓝和小红说:“我们别在联系”时,只表示小蓝已经没有什么话想和小红说了。这个时候小蓝还可以接收小红发来的数据。
当小红和小蓝说:“你可以不在联系我”的时候,小红知道小蓝已经没有话要和我说了,但是我还可以向她发送数据。
当小红对小蓝说:“我也要和你不在联系”时,说明小红也无话可说了,此后双方就和平的断开这次连接。
综上所述,四次挥手以最低成本断开了双方的连接。
介绍:MSL指的是一段TCP报文在传输过程中的最大生命周期。2MSL即是服务器端发出为FIN报文和客户端发出的ACK确认报文所能保持有效的时长。
和第三次挥手一样的道理,第四次挥手是不可靠的,可能丢失。为了确认服务端是否收到了客户端发出的确认报文,所以在客户端发送完ACK确认报文之后,会设置一个时长为2MSL的计时器。
1.服务端如果在1MSL内没有收到客户端发来的ACK确认包,就会再次向客户端发送FIN报文。
2.如果在2MSL内,再次收到了来自服务端的FIN报文,说明服务端没有收到确认。当客户端再次发送确认后,计时器重置为2MSL。
3.如果客户端在2MSL的时间内没有再次收到来自服务端的FIN报文,说明服务端征程接收到了ACK确认报文,客户端进入到CLOSED状态,“四次挥手”完成。
4.综上所述,客户端要经历2MSL的TIME_WAIT状态,这也是为什么客户端比服务器晚进入CLOSED阶段的原因。
1.对于主动断开连接的一方来说,会进入到是TIME_WAIT状态。
2.对于被动断开连接的一方来说,两次挥手完成,进入到CLOSE_WAIT状态。
3.因为TCP协议是对等的,上述的描述和谁是C谁是S没有关系。
1.服务器要处理大量的客户端连接。
2.如果是有服务端主动关闭连接,就会产生TIME_WAIT状态。
3.这个连接会占一个通信五元组,如果有新的客户端连接的IP和端口号与TIME_WAIT占用的连接失败,就会bind失败。
解决办法:
服务器没有正确的关闭socket,四次挥手没有正确完成,这是BUG,加上对应的close即可解决问题。