TCP三次握手与四次挥手
问题背景
- 面试中常常问到TCP的三次握手和四次挥手,一过了校招就不记得了。
- 之前总结了TCP协议的一些特性和过程,还不了解建议连接和断开连接的过程
三次握手
-
三次握手的具体过程
- 步骤1
- Client向Server发送SYN(synchronization,本质已经表明了是同步sequence)包,带上Client的sequence, 请求建立连接
- 步骤2
- 服务器收到SYN包,回SYN包,带上服务器的sequence和客户端的sequence对应的确认号
- ACK置为1
- 步骤3
- 客户端接收到服务器回包,知道连接确认
- 回一个ack包,带上服务器的sequence对应的确认号
- 步骤1
-
为什么需要三次,两次行不行?
- 为了实现可靠传输,发送方和接收方始终需要同步sequence, 并且确保两个方向的通信都是正常运行的(最本质和最基础的原因)
- 防止已失效的连接请求又传送到服务器端,因而产生错误(《计算机网络》教材中原话)
- 考虑情况:Client向Server发送了第一条请求报文,但是该报文并未在网络中被丢弃,而是长时间阻滞在某处,而Client收不到Server的ACK,以为该报文丢失,于是重新发送该报文,这次的报文成功到达服务器。该连接成功建立并释放后, 第一次的TCP报文段顺利到达了服务器。
- 如果不使用三次握手,则服务器只需对该报文发出确认,就建立了一个连接
- 第一次发送的,阻滞在网络中的报文到达了服务器,服务器以为是客户端又重新发送了一个连接请求(实际上在客户端那里,该连接早已失效),就又向客户端发送一个确认,但客户端认为他没有发送该请求报文,因此不理睬服务器发送的确认,而服务器以为又建立了一个新的连接,于是一直等待A发来数据,造成了服务器资源的浪费
- 考虑情况:Client向Server发送了第一条请求报文,但是该报文并未在网络中被丢弃,而是长时间阻滞在某处,而Client收不到Server的ACK,以为该报文丢失,于是重新发送该报文,这次的报文成功到达服务器。该连接成功建立并释放后, 第一次的TCP报文段顺利到达了服务器。
-
SYN洪泛攻击
- 在TCP协议中被称为三次握手(Three-way Handshake)的连接过程中,如果一个用户向服务器发送了SYN报文,服务器又发出 SYN+ACK 应答报文后未收到客户端的ACK报文,这种情况下服务器端会再次发送SYN+ACK给客户端,并等待一段时间后丢弃这个未完成的连接,这段时间的长度称为SYN Timeout,一般来说这个时间是分钟的数量级。
- SYN 泛洪攻击所做的就是利用这个SYN Timeout和TCP/IP协议族中的另一个漏洞: 报文传输过程中对报文的源IP地址完全信任进行攻击。SYN 泛洪攻击通过发送大量的伪造 TCP 链接报文而造成大量的 TCP 半连接,服务器端将为了维护这样一个庞大的半连接列表而消耗非常多的资源。这样服务器端将忙于处理攻击者伪造的TCP连接请求而无法处理正常连接请求,甚至会导致堆栈的溢出崩溃
四次挥手
- 四次挥手的具体过程
- 部分细节
- FIN位置1,代表finish
- MSL,最长报文段寿命Maximum Segment Lifetime
- 部分细节
- 该设计解决的问题
- 为什么A在TIME-WAIT状态必须等待2MSL的时间
- 这个ACK报文段有可能丢失,使得处于LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认,B超时重传FIN+ACK报文段,而A能在2MSL时间内收到这个重传的FIN+ACK报文段,接着A重传一次确认,重新启动2MSL计时器,最后A和B都进入到CLOSED状态,若A在TIME-WAIT状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到B重传的FIN+ACK报文段,所以不会再发送一次确认报文段,则B无法正常进入到CLOSED状态。
- A在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。
- 为什么A在TIME-WAIT状态必须等待2MSL的时间
- 为什么连接的时候是三次握手,关闭的时候却是四次握手
- 三次握手时,当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。
- 关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET(可能还有其他数据需要传送),所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
wireShark抓包实践
三次握手
- 握手1: Client发送SYN给Server
- 握手2: Server发送SYN+ACK给Client
- 握手3: Client回复ACK
- 从以上三个样例图也可以看出,sequence和确认号之间的规律确实如理论所言。
四次挥手
- 挥手1:A发送FIN给B
- 挥手2
- 挥手3
- 挥手4
- 从以上四个样例图也可以看出,sequence和确认号之间的规律确实如理论所言。