10-三次握手四次挥手

 三次握手

[root@Rocky ~]# ethtool ens33
    Link detected: yes  #端口正常

[root@Rocky ~]# rpm -ql netcat
/usr/bin/nc

ss -nutlp #查看tcp udp链接端口和进程对应关系
来自于iproute包,代替netstat,netstat 通过遍历 /proc来获取 socket信息,ss 使用 netlink与内核tcp_diag 模块通信获取 socket 信息
-t: tcp协议相关
-u: udp协议相关
-w: 裸套接字相关
-x:unix sock相关
-l: listen状态的连接
-a: 所有
-n: 数字格式
-p: 相关的程序及PID
-e: 扩展的信息
-m:内存用量
-o:计时器信息
传输层通过port号,确定应用层协议,范围0-65535
wang@ubuntu2004:~$ nc -l 1023
nc: Permission denied
0-1023:系统端口或特权端口(仅管理员可用) ,众所周知,永久的分配给固定的系统应用使用,
22/tcp(ssh), 80/tcp(http), 443/tcp(https)
1024-49151:用户端口或注册端口,但要求并不严格,分配给程序注册为某应用使用,
1433/tcp(SqlServer), 1521/tcp(oracle),3306/tcp(mysql),11211/tcp/udp (memcached)
49152-65535:动态或私有端口,客户端随机使用端口,范围定
义:/proc/sys/net/ipv4/ip_local_port_range
注意:当前6000,6665-6669/tcp等端口被Google Chrome 设为默认非安全端口,尽量避免使用
范例: 查看非特权用户可以使用起始端口
[root@Rocky yum.repos.d]# cat /proc/sys/net/ipv4/ip_unprivileged_port_start
1024
范例:调整客户端的动态端口范围
[root@Rocky ~]# cat /proc/sys/net/ipv4/ip_local_port_range
20000    62000

监听22端口

[root@Rocky ~]# nc -l 222 
ss -tnl
LISTEN              0                   10                                        [::]:222
root@ubuntu2004:/etc/apt# nc 192.168.80.171 222
[root@Rocky ~]# ss -nt
State                  Recv-Q             Send-Q                          Local Address:Port                            Peer Address:Port              Process             
CLOSE-WAIT             32                 0                              192.168.80.171:44172                             8.43.85.13:443                                   
ESTAB                  0                  52                             192.168.80.171:22                              192.168.80.1:50060                                 
ESTAB                  0                  0                              192.168.80.171:222                           192.168.80.181:50882 #远程计算机socket
root@ubuntu2004:/etc/apt# nc 192.168.80.171 222
I am ubuntu

 

 

ip.src == 192.168.80.171 and ip.dst==192.168.80.181

 

[root@Rocky ~]# ss -nt
State                  Recv-Q             Send-Q                          Local Address:Port                            Peer Address:Port              Process             
CLOSE-WAIT             32                 0                              192.168.80.171:44172                             8.43.85.13:443                                   
ESTAB                  0                  52                             192.168.80.171:22                              192.168.80.1:50060
root@ubuntu2004:~# ss -nt
State                  Recv-Q             Send-Q                          Local Address:Port                            Peer Address:Port              Process             
ESTAB                  0                  36                             192.168.80.181:22                              192.168.80.1:50065                                 
CLOSE-WAIT             0                  0                              192.168.80.181:50882                         192.168.80.171:222

 

tcpdump -n -t -S -i ens33  port 3334 -w tcp3.cap

 

-i : 指定抓包的网卡是enp0s3
-n: 把域名转成IP显示
-t: 不显示时间
-S: 序列号使用绝对数值,不指定-S的话,序列号会使用相对的数值
port: 指定监听端口是80
host:指定监听的主机名

 

 

 

 

 三系握手过程

第一次握手

客户端将TCP报文标志位SYN置为1,随机产生一个序号值seq=J,保存在TCP首部的序列号(Sequence Number)字段里,指明客户端打算连接的服务器的端口,并将该数据包发送给服务器端,发送完毕后,客户端进入SYN_SENT状态,等待服务器端确认。

第二次握手

服务器端收到数据包后由标志位SYN=1知道客户端请求建立连接,服务器端将TCP报文标志位SYN和ACK都置为1,ack=J+1,随机产生一个序号值seq=K,并将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD状态。

第三次握手

客户端收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给服务器端,服务器端检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。

 

 

 

为什么需要三次握手?

我们假设client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。

本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。

假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。

所以,采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。

TCP 四次挥手关闭连接

 由客户端或服务端任一方执行close来触发。
由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。

四次挥手过程的示意图如下:

 

 

挥手请求可以是Client端,也可以是Server端发起的,我们假设是Client端发起:

  • 第一次挥手: Client端发起挥手请求,向Server端发送标志位是FIN报文段,设置序列号seq,此时,Client端进入FIN_WAIT_1状态,这表示Client端没有数据要发送给Server端了。
  • 第二次分手:Server端收到了Client端发送的FIN报文段,向Client端返回一个标志位是ACK的报文段,ack设为seq加1,Client端进入FIN_WAIT_2状态,Server端告诉Client端,我确认并同意你的关闭请求,Server端进入入CLOSE_WAIT状态。
  • 第三次分手: Server端向Client端发送标志位是FIN的报文段,请求关闭连接,同时Server端进入LAST_ACK状态。
  • 第四次分手 : Client端收到Server端发送的FIN报文段,向Server端发送标志位是ACK的报文段,然后Client端进入TIME_WAIT状态。Server端收到Client端的ACK报文段以后,就关闭连接。此时,Client端等待2MSL的时间后依然没有收到回复,则证明Server端已正常关闭,那好,Client端也可以关闭连接了。

为什么连接的时候是三次握手,关闭的时候却是四次握手?

因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,'你发的FIN报文我收到了'。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

为什么要等待2MSL?

MSL:报文段最大生存时间,它是任何报文段被丢弃前在网络内的最长时间。
有以下两个原因:

第一点:保证TCP协议的全双工连接能够可靠关闭

由于IP协议的不可靠性或者是其它网络原因,导致了Server端没有收到Client端的ACK报文,那么Server端就会在超时之后重新发送FIN,如果此时Client端的连接已经关闭处于CLOESD状态,那么重发的FIN就找不到对应的连接了,从而导致连接错乱,所以,Client端发送完最后的ACK不能直接进入CLOSED状态,而要保持TIME_WAIT,当再次收到FIN的报文,能够保证对方收到ACK,最后正确关闭连接。

第二点:保证这次连接的重复数据段从网络中消失

如果Client端发送最后的ACK直接进入CLOSED状态,然后又再向Server端发起一个新连接,这时不能保证新连接的与刚关闭的连接的端口号是不同的,也就是新连接和老连接的端口号可能一样了,那么就可能出现问题:如果前一次的连接某些数据滞留在网络中,这些延迟数据在建立新连接后到达Client端,由于新老连接的端口号和IP都一样,TCP协议就认为延迟数据是属于新连接的,新连接就会接收到脏数据,这样就会导致数据包混乱。所以TCP连接需要在TIME_WAIT状态等待2倍MSL,才能保证本次连接的所有数据在网络中消失。

posted @ 2022-04-13 08:56  gg888666  阅读(60)  评论(0编辑  收藏  举报