4.6--计算机网络之TCP篇之TCP的连接建立--(复习+深入)---好好沉淀,加油呀

1.TCP 三次握手过程是怎样的?

TCP 是面向连接的协议,所以使用 TCP 前必须先建立连接,而建立连接是通过三次握手来进行的

1.一开始,客户端和服务端都处于 CLOSE 状态。先是服务端主动监听某个端口,处于 LISTEN 状态
2.客户端会随机初始化序号(client_isn),将此序号置于 TCP 首部的「序号」字段中,同时把 SYN 标志位置为 1,表示 SYN 报文。
接着把第一个 SYN 报文发送给服务端,表示向服务端发起连接

该报文不包含应用层数据,之后客户端处于 SYN-SENT 状态

3.服务端收到客户端的 SYN 报文后,首先服务端也随机初始化自己的序号(server_isn),将此序号填入 TCP 首部的「序号」字段中,其次把 TCP 首部的「确认应答号」字段填入 client_isn + 1, 接着把 SYN 和 ACK 标志位置为 1。最后把该报文发给客户端

该报文也不包含应用层数据,之后服务端处于 SYN-RCVD 状态。

4.客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文 TCP 首部 ACK 标志位置为 1 ,其次「确认应答号」字段填入 server_isn + 1 ,最后把报文发送给服务端

这次报文可以携带客户到服务端的数据,之后客户端处于 ESTABLISHED 状态

5.服务端收到客户端的应答报文后,也进入 ESTABLISHED 状态

第三次握手是可以携带数据的,前两次握手是不可以携带数据的

2.为什么是三次握手?不是两次、四次?

1.三次握手才可以阻止重复历史连接的初始化(主要原因)

如果采用两次握手建立 TCP 连接的场景下,服务端在向客户端发送数据前,并没有阻止掉历史连接,导致服务端建立了一个历史连接,又白白发送了数据,妥妥地浪费了服务端的资源

2.三次握手才可以同步双方的初始序列号

两次握手只保证了一方的初始序列号能被对方成功接收,没办法保证双方的初始序列号都能被确认接收

3.三次握手才可以避免资源浪费

由于没有第三次握手,服务端不清楚客户端是否收到了自己回复的 ACK 报文,所以服务端每收到一个 SYN 就只能先主动建立一个连接,这会造成什么情况呢?
如果客户端发送的 SYN 报文在网络中阻塞了,重复发送多次 SYN 报文,那么服务端在收到请求后就会建立多个冗余的无效链接,造成不必要的资源浪费

TCP 建立连接时,通过三次握手能防止历史连接的建立,能减少双方不必要的资源开销,能帮助双方同步初始化序列号。序列号能够保证数据包不重复、不丢弃和按序传输。

不使用「两次握手」和「四次握手」的原因:

1.「两次握手」:无法防止历史连接的建立,会造成双方资源的浪费,也无法可靠的同步双方序列号;
2.「四次握手」:三次握手就已经理论上最少可靠连接建立,所以不需要使用更多的通信次数。

3.为什么每次建立 TCP 连接时,初始化的序列号都要求不一样呢?

主要原因有两个方面:

1.为了防止历史报文被下一个相同四元组的连接接收(主要方面);
2.为了安全性,防止黑客伪造的相同序列号的 TCP 报文被对方接收

如果每次建立连接,客户端和服务端的初始化序列号都是一样的话,就有大概率遇到历史报文的序列号刚「好在」对方的接收窗口内,从而导致历史报文被新连接成功接收。

每次初始化序列号不一样很大程度上能够避免历史报文被下一个相同四元组的连接接收
是很大程度上,并不是完全避免了(因为序列号会有回绕的问题,所以需要用时间戳的机制来判断历史报文)

4.初始序列号 ISN 是如何随机产生的?

初始化序列号 ISN 随机生成算法:ISN = M + F(localhost, localport, remotehost, remoteport)。

1.M 是一个计时器,这个计时器每隔 4 微秒加 1。
2.F 是一个 Hash 算法,根据源 IP、目的 IP、源端口、目的端口生成一个随机数值。
要保证 Hash 算法不能被外部轻易推算得出,用 MD5 算法是一个比较好的选择。

随机数是会基于时钟计时器递增的,基本不可能会随机成一样的初始化序列号

5.既然 IP 层会分片,为什么 TCP 层还需要 MSS 呢?

MTU:一个网络包的最大长度,以太网中一般为 1500 字节;
MSS:除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大长度;

果一个 IP 分片丢失,整个 IP 报文的所有分片都得重传

当某一个 IP 分片丢失后,接收方的 IP 层就无法组装成一个完整的 TCP 报文(头部 + 数据),也就无法将数据报文送到 TCP 层,所以接收方不会响应 ACK 给发送方,因为发送方迟迟收不到 ACK 确认报文,所以会触发超时重传,就会重发「整个 TCP 报文(头部 + 数据)」

6.第一次握手丢失了,会发生什么?

1.当客户端想和服务端建立 TCP 连接的时候,首先第一个发的就是 SYN 报文,然后进入到 SYN_SENT 状态。

2.在这之后,如果客户端迟迟收不到服务端的 SYN-ACK 报文(第二次握手),就会触发「超时重传」机制,重传 SYN 报文,而且重传的 SYN 报文的序列号都是一样的

客户端的 SYN 报文最大重传次数由 tcp_syn_retries内核参数控制,这个参数是可以自定义的,默认值一般是 5。

当第五次超时重传后,会继续等待 32 秒,(每次超时的时间是上一次的 2 倍)如果服务端仍然没有回应 ACK,客户端就不再发送 SYN 包,然后断开 TCP 连接

7.第二次握手丢失了,会发生什么?

第二次握手的 SYN-ACK 报文其实有两个目的 :

第二次握手里的 ACK, 是对第一次握手的确认报文;
第二次握手里的 SYN,是服务端发起建立 TCP 连接的报文;

1.如果客户端迟迟没有收到第二次握手,那么客户端就觉得可能自己的 SYN 报文(第一次握手)丢失了,于是客户端就会触发超时重传机制,重传 SYN 报文。
2.如果第二次握手丢失了,服务端就收不到第三次握手,于是服务端这边会触发超时重传机制,重传 SYN-ACK 报文

因此,当第二次握手丢失了,客户端和服务端都会重传:

1.客户端会重传 SYN 报文,也就是第一次握手,最大重传次数由 tcp_syn_retries内核参数决定;
2.服务端会重传 SYN-ACK 报文,也就是第二次握手,最大重传次数由 tcp_synack_retries 内核参数决定

8.第三次握手丢失了,会发生什么?

第三次握手的 ACK 是对第二次握手的 SYN 的确认报文

所以当第三次握手丢失了,如果服务端那一方迟迟收不到这个确认报文,就会触发超时重传机制,重传 SYN-ACK 报文,直到收到第三次握手,或者达到最大重传次数。

ACK 报文是不会有重传的,当 ACK 丢失了,就由对方重传对应的报文

9.什么是 SYN 攻击?如何避免 SYN 攻击?

在这里插入图片描述

在 TCP 三次握手的时候,Linux 内核会维护两个队列,分别是:

1.半连接队列,也称 SYN 队列;
2.全连接队列,也称 accept 队列;

SYN攻击:
攻击者短时间伪造不同 IP 地址的 SYN 报文,服务端每接收到一个 SYN 报文,就进入SYN_RCVD 状态,但服务端发送出去的 ACK + SYN 报文,无法得到未知 IP 主机的 ACK 应答,久而久之就会占满服务端的半连接队列,使得服务端不能为正常用户服务

正常流程:

1.当服务端接收到客户端的 SYN 报文时,会创建一个半连接的对象,然后将其加入到内核的「 SYN 队列」;
2.接着发送 SYN + ACK 给客户端,等待客户端回应 ACK 报文;
3.服务端接收到 ACK 报文后,从「 SYN 队列」取出一个半连接对象,然后创建一个新的连接对象放入到「 Accept 队列」;
4.应用通过调用 accpet() socket 接口,从「 Accept 队列」取出连接对象

SYN 攻击方式最直接的表现就会把 TCP 半连接队列打满,这样当 TCP 半连接队列满了,后续再在收到 SYN 报文就会丢弃,导致客户端无法和服务端建立连接

不管是半连接队列还是全连接队列,都有最大长度限制,超过限制时,默认情况都会丢弃报文

避免 SYN 攻击方式,可以有以下四种方法:

1.调大 netdev_max_backlog;
2.增大 TCP 半连接队列;
3.开启 tcp_syncookies;
4.减少 SYN+ACK 重传次数

方式一:调大 netdev_max_backlog

当网卡接收数据包的速度大于内核处理的速度时,会有一个队列保存这些数据包。控制该队列的最大值如下参数,默认值是 1000,我们要适当调大该参数的值,比如设置为 10000:

net.core.netdev_max_backlog = 10000

方式二:增大 TCP 半连接队列

方式三:开启 net.ipv4.tcp_syncookies

net.ipv4.tcp_syncookies 参数主要有以下三个值:

0 值,表示关闭该功能;
1 值,表示仅当 SYN 半连接队列放不下时,再启用它;
2 值,表示无条件开启功能; 那么在应对 SYN
攻击时,只需要设置为 1 即可

方式四:减少 SYN+ACK 重传次数

减少 SYN-ACK 的重传次数,以加快处于 SYN_REVC 状态的 TCP 连接断开。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值