TCP之三次握手、四次挥手

TCP之三次握手、四次挥手

前言

因为对于TCP而言,是默认的全双工协议,因此可以是客户端向服务器端发起连接,也可以是服务端向客户端发起连接。在这里,我们以客户端向服务端发起连接请求。

大体过程

TCP协议流程图

详细介绍

下面,我们分别介绍下一些专有名词:

  1. SYN:发起一个新的连接
  2. ACK:代表确认序列号生效
  3. SEQ:序列号:代表的是从源端到目标端的序列号
  4. ACK:确认序列号,一般为接收到的SEQ +1,并且只有在ACKFlag位为1的时候生效
  5. FIN:释放一个连接
  6. MSL: 最大报文生成时间

三次握手流程

  1. server端 开放了某个端口后,此时 会从CLOSED 阶段 进入到LISTEN 接口
  2. client想要连接server的时候,此时会从 发送一个 SYN 报文,同时从CLOSED 阶段进入到SYN-SENT阶段。
  3. server收到了来自clientSYN后,此时会从 LISTEN 阶段 转到 SYN-RCVD 接口,同时通知clientACKSYN
  4. client接收到server的确认和请求连接后,发送ACK告知server端,同时 client 端从SYN-SENT 阶段 进入到ESTABLISHED 阶段
  5. server收到了client的确认后,也从 SYN-RCVD 阶段 进入到 ESTABLISHED 阶段

为什么要三次握手?

  1. 保证服务器资源的防止浪费的情况,如果是两次握手,就会出现当网络阻塞,客户端没有在一定的时间内收到服务端的请求,此时客户端会重新启动一个新的连接,此时客户端又会启动一个新的端口连接对应。此时就会出现服务器端资源浪费的情况
  2. 因为有SEQ的版本控制问题,当有一个请求包在网络阻塞很久之后,到达server端,server端可以根据SEQ判断当前的包是否是有效的数据包

为什么不是四次握手?

没有必要,因为三次已经能够保证全双工了

四次挥手流程

  1. client准备关闭与server的连接时,此时会发送一个报文通知server端,同时客户端会从 ESTABLISHED 状态进入到 FIN-WAIT-1 状态,此时客户端处于半关闭状态,已经无法通过clientserver发送数据包,但是允许接收serverclient的数据包。这里要注意一点,这里client不能向server发送的仅仅是数据包,不代表不能发送确认包。
  2. server端收到了client端想要断开连接的请求后,此时server会从 ESTABLISHED 状态进入到CLOSE-WAIT状态。此时客户端也进入了一个半关闭的状态。
  3. 当执行完第2步骤后,此时client端接收到了server的确认,则可以正式的关闭了从client端到server端的连接。并且进入到 FIN-WAIT-2 阶段。
  4. server端经历过 CLOSE_WAIT 阶段后,并且做好了与客户端断开连接的准备后,此时server端会向client发送关闭从server端到client端的连接的请求,并且自动进入到 LAST-ACK 阶段。在这个阶段,server端不在向client端发送任何数据,但是允许接收从client发送过来的确认包。
  5. client端收到了server端的主动关闭请求后,此时会从FIN-WAIT-2阶段到 TIME-WAITED 阶段。并且告知server端已收到关闭请求通知。
  6. server端接收到回应后,此时会停止 CLOSE-WAIT 阶段,进入 CLOSED 阶段。在这个时候,已经正式的确认了从 serverclient端的连接的关闭。
  7. 当客户端发送了server端关闭请求的回应后,等到2MSL,自动进入CLOSED 阶段,在这个时候,已经正式的确认了从clientserver端的连接的关闭。

为什么客户端的TIME_WAIT需要2MSL

为了保证server端能够最大安全的关闭:

  1. 如果client2MSL时间内,再次收到了来自serverFIN报文,说明server由于各种原因没有接收到client发出的ACK确认报文。client再次向server发出ACK确认报文,计时器重置,重新开始2MSL的计时
  2. client2MSL内没有再次收到来自serverFIN报文,说明server正常接收了ACK确认报文,client可以进入CLOSED阶段

SYN攻击

原理

  1. client伪造大量的虚拟IP,并向server端发送SYN
  2. server端收到后,发送 ACK +SYN包给虚拟IP
  3. 因为虚拟IP不存在,所以不会回应server端的 ACK+SYN
  4. server端收不到确认后,此时会认为是确认包丢失,此时会不断重发,直到超时

因为这些虚拟的SYN包会长期占用未连接队列,就会导致真实的client端请求无法加入到队列中,从而被丢弃,最终造成网络拥堵和瘫痪。

Linux系统中,我们可以采用netstat -nap | grep SYN_RECV命令进行查看

系统存在大量的TIME_WAIT:

原因

  1. 系统中存在非常频繁的 TCP连接打开-关闭的进程
  2. 网络状态不太好,server端总是在2MSL的时间内,重新发送 FIN 关闭请求,导致 client端总是在重置2MSL

危害

  1. 消耗系统的连接数
  2. 过多的消耗内存,平均一个 TIME-WAIT要占用4K大小的内存

解决方案

1.vi /etc/sysctl.conf

#表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_syncookies = 1    
#表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1       
#表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1    
#修改系統默认的 TIMEOUT 时间。
net.ipv4.tcp_fin_timeout        

#表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
net.ipv4.tcp_keepalive_time = 1200   
#表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为10000到65000。(注意:这里不要将最低值设的太低,否则可能会占用掉正常的端口!)
net.ipv4.ip_local_port_range = 10000 65000   
#表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_syn_backlog = 8192
#表示系统同时保持TIME_WAIT的最大数量,如果超过这个数字,TIME_WAIT将立刻被清除并打印警告信息。默 认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于 Squid,效果却不大。此项参数可以控制TIME_WAIT的最大数量,避免Squid服务器被大量的TIME_WAIT拖死
net.ipv4.tcp_max_tw_buckets = 5000

2./sbin/sysctl -p

转载请注明来源,欢迎指出任何有错误或不够清晰的表达。可以邮件至 gouqiangshen@126.com

文章标题:TCP之三次握手、四次挥手

文章字数:1.7k

本文作者:BiggerShen

发布时间:2020-08-24, 21:57:41

最后更新:2024-01-16, 03:51:15

原始链接:https://shengouqiang.cn/NetWork/NetWorkLearnDay01/

版权声明: 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏