tcp通过3次握手建立tcp连接。
client状态:closed->syn_sent->establish
server状态:closed->syn_rcvd->establish
报文如下:
client 报文 server
syn_sent >>>>>>syn=1 seq=k>>>>>>>>>>>>>>syn_rcvd
establish <<<<<<syn=1 ACK=1 ack=k+1 seq=j<<syn_rcvd
establish >>>>>>ACK=1 ack=j+1>>>>>>>>>>>>>establish
dos攻击是在syn_sent与establish之间发起大量来至不同ip的syn包,server回复确认包,并等待client的确认,在这个过程大量等待,占用队列。
tcp连接通过4次握手实现断开,因为tcp是双工的,每个方向各自断开
client状态:establish->fin_wait_1->fin_wait_2->time_wait->closed
server状态:establish->close_wait->last_ack->closed
先发去断开可以是客户端也可以服务端,先发去断开状态先进入fin_wait_2
报文如下(假定client先发去断开):
client 报文 server
fin_wait_1>>>>>>fin m>>>>>>>>>>> close_wait
fin_wait_2<<<<<<fin m+1<<<<<<<<<close_wait
time_wait<<<<<<<fin k<<<<<<<<<<<last_ack
time_wait>>>>>>>fin k+1>>>>>>>>>closed
closed
time_wait是不能立即释放,还需要等待2msl,确保ack包可能的丢失。
为什么建立连接是3次握手而断开连接是4次握手:
建立连接是客户端发送syn包,服务端见syn和ack合在一个报文返回给client,所以只有3次握手,由于tcp是双工的,断开连接时需要每个方向单独断开,关闭一个方向连接时,仅表示该方向没有数据传输,但另外一个方向还能有数据传输。
fin_wait_2没有超时机制,如果连接只关闭一个方向,则会出现该状态持续存在而不是释放,如果大量存在则会导致内核crash
主动关闭方:estabish->fin_wait1->fin_wait2->time_wait
被动关闭方:estabish->close_wait->last_ack->close
time_wait:预留2msl的时间窗
1、避免被动方接受确认包失败ack(fin),重发fin报文,如果主动方直接关闭,则不会回复ack报文
2、在时间窗内,让本次连接的消息包消失,避免影响下个连接
time_wait会随着时间推移消失,如果短时间内大量time_wait出现,可以通过加速服务器回收和重用time_wait资源
close_wait出现原因是逻辑代码里,主动方关闭了连接,使被动方处理close_wait状态,但被动方没有主动释放连接,一致占用资源。
网友评论