TCP三次握手

TCP三次握手是客户端和服务端建立连接的方式,下面先让我们来看一下近一步来看一下TCP的三次握手的相关细节

一、TCP三次握手的过程

这里引用一下小林图解网络里面画的TCP三次握手的流程图。

通过流程图,我们可以看到:

第一次握手:

⼀开始,客户端和服务端都处于 CLOSED 状态。

服务端:主动监听某个端⼝,处于 LISTEN 状态。
客户端:随机初始化序号( client_isn ),将此序号置于 TCP ⾸部的「序号」字段中,同时把
SYN 标志位置为 1 ,表示 SYN 报⽂。接着把第⼀个 SYN 报⽂发送给服务端,表示向服务端发起连接,该报⽂不包含应⽤层数据,之后客户端处于 SYN-SENT 状态。

第二次握手:
服务端:在收到客户端的 SYN 报⽂后,服务端也随机初始化⾃⼰的序号( server_isn ),将此序号填⼊TCP ⾸部的「序号」字段中,其次把 TCP ⾸部的「确认应答号」字段填⼊ client_isn + 1 , 接着把SYN和 ACK 标志位置为 1 。最后把该报⽂发给客户端,该报⽂也不包含应⽤层数据,之后服务端处于SYN-RCVD 状态。

第三次握手:
客户端:在收到服务端报⽂后,还要向服务端回应最后⼀个应答报⽂,⾸先该应答报⽂ TCP ⾸部 ACK标志位置为 1 ,其次「确认应答号」字段填⼊ server_isn + 1 ,最后把报⽂发送给服务端,这次报⽂可以携带客户到服务器的数据,之后客户端处于 ESTABLISHED 状态。
服务端:收到客户端的应答报⽂后,也进⼊ ESTABLISHED 状态。 

二、TCP报文的头部格式及状态的查看

其中TCP报文的头部格式如下图所示。

可以看到其中包含32位序列号和32位确认应答号。还有ACK,SYN等标志位。在第二次握手的过程中,服务端正是将客户端报文中的序列号+1作为确认应答号,并将SYN标志位置为1作为ACK+SYN报文返回客户端。

可通过netstat -napt来对TCP的状态进行查看

 三、TCP为什么是三次握手而不是两次或者四次握手?

这里分别解释:

1)不用两次握手

我们先来试想一种情况(可以参考下面的图),如果在第一次握手的过程中,客户端向服务端发送了SYN报文(Num=90),但由于网络原因使得报文阻塞,在一段时间没有收到服务端的响应报文后,客户端会再次发送SYN报文(Num=100)。假如此时,之前发送的被阻塞的报文(Num=90)恰好到达了服务端,此时服务端会进行第二次握手,即发送SYN+ACK报文给客户端。试想一下,如果两次握手即可建立连接,在这种情况下,客户端和服务端将会基于旧的报文建立连接,此时可能会造成错误。

 而在三次握手的机制下,客户端就可以根据确认应答号判断所接受到的ACK+SYN报文是不是历史连接,并根据是否为历史连接做出不同的应答。

如果是历史连接,则第三次握⼿发送的报⽂是 RST 报⽂,以此中⽌历史连接;
如果不是历史连接,则第三次发送的报⽂是 ACK 报⽂,通信双⽅就会成功建⽴连接

这样就可以避免建立历史连接了,这是两次握手没法做到的。

还有一个原因,那就是客户端和服务端要同步双方的初始序列号

第二次握手中,服务端在确认应答号中将客户端在第一次握手中生成的随机序列号+1,表示对客户端SYN报文的成功接收,那么客户端也同样需要一个握手过程表示对服务端报文的成功接收。因此,这就是第三次握手的必要性。

2)不用四次握手

其实通过刚才的过程我们可以看到,三次握手已经可以建立可靠的TCP连接了,因此,实在是没有必要再增加一次握手过程,白白增加资源的浪费。

四、SYN攻击及应对措施

什么是SYN攻击?

我们都知道 TCP 连接建⽴是需要三次握⼿,假设攻击者短时间伪造不同 IP 地址的 SYN 报⽂,服务端每接收到 ⼀个 SYN 报⽂,就进⼊ SYN_RCVD 状态,但服务端发送出去的 ACK + SYN 报⽂,⽆法得到未知 IP 主机的 ACK 应答,久⽽久之就会占满服务端的 SYN 接收队列,使得服务器不能为正常⽤户服务。

 如何应对SYN攻击?

1.通过参数设置连接队列的大小和队列满的时候该做什么处理
net.core.netdev_max_backlog //连接队列大小
net.ipv4.tcp_max_syn_backlog //处于SYN_RCVD状态的连接的最大个数
net.ipv4.tcp_abort_on_overflow //连接队列满时,对新的SYN回报RST

该方法的原理是通过预先设定的SYN队列的大小和处于SYN_RVCD状态的连接数来对SYN攻击进行应对,当SYN队列满或者SYN_RCVD的连接数超过设定值时,对新的SYN报文回报RST即终止建立连接。

2.设置net.ipv4.tcp_syncookies = 1

即开启cookie模式
当 「 SYN 队列」满之后,后续服务端收到 SYN 包后,这些SYN包将不进⼊「 SYN 队列」,此时服务端将会计算出⼀个 cookie 值,再以 SYN + ACK 中的「序列号」返回客户端,(key-value),之后,在第三次握手中客户端会发送ACK报文进行相应,服务端接收到客户端的响应报⽂时,服务器会检查这个 ACK 包的合法性。如果合法,直接放⼊到「 Accept 队列」。
最后应⽤通过调⽤ accpet() socket 接⼝,从「 Accept 队列」取出的连接。

五、TCP的序列号为什么是随机的?如果不是随机的会怎么样?

因为第二次握手和第三次握手的过程中,服务端和客户端要分别对对方发送的报文进行相应。响应的实现就是把对方在之前报文中生成的序列号+1作为确认应答号加入报文中。如果这个序列号不是随机生成的话,或者说可以被推测出来的话,那么黑客就会根据推测出来的序列号,伪装成服务端与客户端建立连接,从而威胁客户端的数据安全。因此,为了保证网络安全,TCP的序列号必须随机生成。

六、如果TCP三次握手的最后一次握手中出现丢包的情况会怎么样?

首先,第三次握手的ACK报文发出之后,客户端就进入了established状态,即认为连接建立成功。但服务端由于没有收到ACK报文,则不会成功建立连接。

但服务端会有定时器发送第二步SYN+ACK数据包的功能,此操作可使得客户端有机会再次发送ACK包,如果客户端再次发送ACK包成功,建立连接。

如果还是失败,服务器会启动有超时(大概64s)设置,超时之后会给客户端发RTS报文,进入
CLOSED状态,防止SYN洪泛攻击,这个时候客户端应该也会关闭连接。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值