三次握手和四次挥手
2021-04-26 15:38:21 2 举报
AI智能生成
三次握手和四次挥手原理及面试常见问题
作者其他创作
大纲/内容
状态
普通字段
ACK报文
用来应答
SYN报文
用来同步
LISTEN
侦听来自远方TCP端口的链接请求
SYN-SENT
在发送连接请求后等待匹配的连接请求
SYN-RECEIVED
在收到和发送一个连接请求后等待对连接请求的确认
ESTABLISHED
代表一个打开的连接,数据可以传送给用户
FIN-WAIT-1
等待远程TCP的连接中断请求,或先前的连接中断请求的确认
FIN-WAIT-2
从远程TCP等待连接中断请求
CLOSE-WAIT
等待从本地用户发来的连接中断请求
CLOSING
等待远程TCP对连接终端的确认
LAST-ACK
等待原来发向远程TCP的连接终端请求的确认
TIME-WAIT
等待足够的时间以确保远程TCP接收到连接中断请求的确认
CLOSED
没有任何链接状态
重点字段
序号
Seq序号
占32位
用来标识从TCP源端向目的地端发送的字节流,发起方发送数据时对此进行标记
确认序号
Ack序号
占32位
只用ACK标志位为1时,确认序号字段才有效,Ack=Seq+1
URG
紧急指针(urgent pointer)有效
ACK
确认序号有效(用来应答)
SYN
发起一个新连接(用来同步)
PSH
接收方应该尽快将这个报文交给应用层
RST
重置连接
FIN
释放一个连接
注意
不要将确认序号Ack与标志位中的ACK搞混
确认方Ack=发起方Req+1,两端配对
三次握手
原理
初始
客户端处于Closed状态,服务端处于Listen状态
第一次握手
客户端给服务端发一个SYN报文,并指明客户端的初始化序列号ISN(c)
此时客户端处于SYN_SENT状态
第二次握手
服务器收到客户端的SYN报文之后,会以自己的SYN报文作为应答,并且也是指定了自己的初始化序列号ISN(s)
同时会把客户端的ISN+1作为ACK的值,表示自己已经收到了客户端的SYN
此时服务器处于SYN_RCVD状态
第三次握手
客户端收到SYN报文呢后,会发送一个ACK报文,一样是把服务器的ISN+1作为ACK的值,表示收到了服务器的SYN报文
此时客户端处于ESTABLISHED状态
服务器收到ACK报文后,也处于ESTABLISHED状态,此时双方已建立起了连接
作用
确认双方的接受能力、发送能力是否正常
指定自己的初始化序列号,为后面的可靠传送做准备
如果是HTTPS协议,三次握手过程中,还会进行数字证书的验证以及加密密钥的生成
问题
为什么需要三次握手,两次不行吗?
思路
弄清楚三次握手的目的,再考虑是否能用两次握手来达到同样的结果
第一次握手
客户端发送网络包,服务端收到了
服务端结论
客户端的发送能力、服务端的接收能力正常
第二次握手
服务端发包,客户端收到了
客户端结论
服务端的接收、发送能力,客户端的接收、发送能力是正常的
不过此时服务器并不能确认客户端的接收能力是否正常
不过此时服务器并不能确认客户端的接收能力是否正常
第三次握手
客户端发包,服务端收到了
服务端结论
客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常
所以需要三次握手才能确认双方的接受和发送能力是否正常
第三次握手的必要性
如客户端发出连接请求,但因连接请求报文丢失而未收到确认,于是客户端再重传一次连接请求。
后来收到了确认,建立了连接。数据传输完毕后,就释放了连接,客户端共发出了两个连接请求报文段,其中第一个丢失,第二个到达了服务端,但是第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到连接释放以后的某个时间才到达服务端,此时服务端误认为客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同意建立连接,不采用三次握手,只要服务端发出确认,就建立新的连接了,此时客户端忽略服务端发来的确认,也不发送数据,则服务端一致等待客户端发送数据,浪费资源。
后来收到了确认,建立了连接。数据传输完毕后,就释放了连接,客户端共发出了两个连接请求报文段,其中第一个丢失,第二个到达了服务端,但是第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到连接释放以后的某个时间才到达服务端,此时服务端误认为客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同意建立连接,不采用三次握手,只要服务端发出确认,就建立新的连接了,此时客户端忽略服务端发来的确认,也不发送数据,则服务端一致等待客户端发送数据,浪费资源。
(ISN)是固定的吗?
当一端为建立连接而发送它的SYN时,它为连接选择一个初始序号。ISN随时间而变化,因此每个连接都将具有不同的ISN。ISN可以看作是一个32比特的计数器,每4ms加1 。这样选择序号的目的在于防止在网络中被延迟的分组在以后又被传送,而导致某个连接的一方对它做错误的解释。
三次握手的其中一个重要功能是客户端和服务端交换 ISN(Initial Sequence Number),以便让对方知道接下来接收数据的时候如何按序列号组装数据。如果 ISN 是固定的,攻击者很容易猜出后续的确认号,因此 ISN 是动态生成的
为什么是半连接队列?
半连接队列
服务器第一次收到客户端的 SYN 之后,就会处于 SYN_RCVD 状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列
全连接队列
已经完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象
SYN-ACK重传次数
服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传。如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。
注意,每次重传等待的时间不一定相同,一般会是指数增长,例如间隔时间为 1s,2s,4s,8s…
注意,每次重传等待的时间不一定相同,一般会是指数增长,例如间隔时间为 1s,2s,4s,8s…
三次握手过程中可以携带数据吗?
第三次握手的时候,是可以携带数据的。但是,第一次、第二次握手不可以携带数据
第一次握手不可以放数据,其中一个简单的原因就是会让服务器更加容易受到攻击了。
而对于第三次的话,此时客户端已经处于 ESTABLISHED 状态。对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据也没啥毛病。
而对于第三次的话,此时客户端已经处于 ESTABLISHED 状态。对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据也没啥毛病。
SYN攻击
什么是SYN攻击(SYN FLOOD)?
定义
SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复确认包,并等待Client确认,由于源地址不存在,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪
SYN 攻击是一种典型的 DoS/DDoS 攻击
补充
服务器端的资源分配是在二次握手时分配的,而客户端的资源是在完成三次握手时分配的,所以服务器容易受到SYN洪泛攻击
如何检测SYN攻击?
你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击
在 Linux/Unix 上可以使用系统自带的 netstat 命令来检测 SYN 攻击
netstat -n -p TCP | grep SYN_RECV
如何防御SYN攻击?
缩短超时(SYN Timeout)时间
增加最大半连接数
过滤网关防护
SYN cookies技术
四次挥手
原理
初始
双方都处于ESTABLISHED状态,假如是客户端先发起关闭请求
第一次挥手
客户端发送一个FIN报文,报文中会指定一个序列号
此时客户端处于FIN_WAIT_1状态
第二次挥手
服务端收到FIN之后,会发送ACK报文,且把客户端的序列号值+1作为ACK报文的序列号,表明已经收到客户端的报文了
此时服务端处于CLOSE_WAIT状态
第三次挥手
如果服务端也想断开连接了,和客户端的第一次挥手一样,发给FIN报文,且指定一个序列号
此时服务端处于LAST_ACK状态
第四次挥手
客户端收到FIN之后,一样发送一个ACK报文作为应答,且把服务端的序列号值+1作为自己ACK报文的序列号值
此时客户端处于TIME_WAIT状态
需要过一段时间后以确保服务段收到自己的ACK报文之后才会进入CLOSED状态,服务端收到ACK报文之后,就关闭连接了,处于CLOSED状态
问题
(TIME_WAIT)为什么客户端发送ACK之后不直接关闭,而是要等一阵子才关闭?
对一个具体实现所给定的MSL值,处理的原则是:当TCP执行一个主动关闭,并发回最后一个ACK,该连接必须在TIME_WAIT状态停留的时间为2倍的MSL。这样可让TCP再次发送最后的ACK以防这个ACK丢失(另一端超时并重发最后的FIN)
这种2MSL等待的另一个结果是这个TCP连接在2MSL等待期间,定义这个连接的插口(客户的IP地址和端口号,服务器的IP地址和端口号)不能再被使用。这个连接只能在2MSL结束后才能再被使用
挥手为什么需要四次?
因为当服务端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当服务端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉客户端,“你发的FIN报文我收到了”。只有等到我服务端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四次挥手。
四次挥手释放连接时,等待2MSL的意义??
MSL
Maximum Segment Lifetime的英文缩写,可译为“最长报文段寿命”,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
为了保证客户端发送的最后一个ACK报文段能够到达服务器。因为这个ACK有可能丢失,从而导致处在LAST-ACK状态的服务器收不到对FIN-ACK的确认报文。服务器会超时重传这个FIN-ACK,接着客户端再重传一次确认,重新启动时间等待计时器。最后客户端和服务器都能正常的关闭。假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSED状态?
理论上,四个报文都发送完毕,就可以直接进入CLOSE状态了,但是可能网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文
0 条评论
下一页