1、什么是三次握手?
简略版:
1、第一次握手:客户端给服务器发送一个SYN=1的请求报文,
2、第二次握手:服务器收到SYN报文,说明客服端的发送能力正常,此时服务器会应答一个SYN+ACK报文,
3、第三次握手:客户端收到SYN+ACK报文,说明服务器的收发能力正常,客服端的接收能力正常,此时客户端会回应一个ACK报文,
4、服务器收到ACK报文后,服务器才能知道客户端接收报文能力正常,三次握手建立完成
详细版:
刚开始客户端处于closed的状态,服务端处于listen状态。然后
1、第一次握手:客户端给服务端发一个SYN报文,并指明客户端的初始化序列号ISN©。此时客户端处于SYN_Send状态。
2、第二次握手:服务器收到客户端的SYN报文之后,会以自己的SYN报文作为应答,并且也是指定自己的初始化序列号ISN(s),同时会把客户端的ISN+1作为ACK的值,表示自己已经收到客户端的SYN,此时服务器处于SYN_REVD的状态。
3、第三次握手:客户端收到SYN报文之后,会发送一个ACK报文,当然也是一样把服务器的ISN+1作为ACK的值,表示已经收到了服务器是SYN报文,此时客户端处于establised状态。
4、服务器收到ACK报文之后,也处于establised状态,此时,双方以建立起了连接。
2、三次握手的作用
1、确保双方的接收能力与发送能力是否正常。
2、指定自己的初始化序列号,为后面的可靠传送做准备。
3、ISN是固定的吗?
三次握手的一个重要功能是客户端和服务器交换ISN(Initial SequenceNumber),以便让对方知道接下来接受数据的时候如何按照序列号组装数据。
如果ISN是固定的,攻击者很容易猜出后续的确认号,因此ISN是动态生成的。
4、什么是半连接队列
服务器第一次接收到客户端的SYN后,就会处于SYN_REVD状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。当然还有一个全连接队列,就是已经完成三次握手,建立起的连接的就会放在全连接队列中。如果队列满了就有可能出现丢包现象。
5、SYN-ACK重传次数
当服务器发送完SYN-ACK包后,如果未收到客户端确认包,服务器会进行首次重传,等待一段时间后仍未收到客户端确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同,一般会是指数增长,例如间隔时间为1s,2s,4s,8s等
6、三次握手可以携带数据吗?
第一次和第二次握手不可以携带数据,但是第三次握手是可以携带数据的。
如果第一次握手可以携带数据的话,攻击者完全可以不理会服务器的接收,发送能力是否正常,疯狂重复发SYN报文,服务器会花费很多时间和内存来接收这些报文。这样会使得服务器容易受到攻击。
第二次也是一样的,如果服务器疯狂给客户端发送报文,也会使客户端收到攻击
而对于第三次的话,此时客户端已经处于established状态,也就是说,对于客户端来说,已经建立起连接,并且也知道服务器的接收、发送能力正常,所以能携带数据页。
7、四次挥手
刚开始双方都处于established状态,假如是客户端先发起关闭请求,则:
1、第一次挥手:客户端发送一个FIN报文,报文中会指定一个序列号。此时客户端处于CLOSED_WAIT1状态。
2、第二次挥手:服务器收到FIN之后,会发送ACK报文,而且会把客户端的序列号值+1作为ACK报文的序列号值,表明已经收到客户端的报文了,此时服务器处于CLOSE_WAIT2状态。
3、第三次挥手:如果服务器也想断开连接,和客户端的第一次挥手一样,发送FIN报文,且指定一个序列号。此时服务器处于LAST_ACK状态。
4、第四次挥手:客户端收到FIN之后,一样发送一个ACK报文作为应答,而且把服务器的序列号值+1作为自己ACK报文序列号值,此时客户端处于TIME_WAIT状态。需要经过一段时间以确保服务器收到自己的ACK报文之后才会进入CLOSED状态。
5、服务器收到ACK报文之后,关闭连接,处于CLOSED状态。