Linux的SSH为什么卡住了?
SSH
零、ssh的三个重要过程
维基百科对ssh的介绍:https://en.wikipedia.org/wiki/Secure_Shell
RFC-4253当中的ssh的介绍:https://www.rfc-editor.org/rfc/rfc4253#section-4
第一步:先是三次握手,测试一下端口是否通畅(这个地方容易如果被卡住了,会在wireshark当中出现大量的重传),如下图所示,客户端(80.100)发送完第一次握手的时候,服务端立马拒绝,客户端再发,服务端再拒绝,客户端连发五次,如果服务器还会拒绝,那就放弃;
第二步:双方相互明确SSH版本(如果在这在一步卡住了,在wireshark当中会出现大量的reset报文),如下图所示,服务端强调自己的版本是ssh2,客户端就直接向服务器发送了RST请求,要求中断。
第三步:相互交换秘钥(如果在这个地方卡住了,一般是因为对方没有与自己匹配的密钥交换算法,会一起卡在INIT状态),如下所示,
第四步:反向解析(如果在这个地方卡住了,问题不大,会延迟大概10秒钟左右才能继续进行)
一、如果你的DNS是假的或不存在
因为工作原因我平时用ssh还是挺多的,但从来没有好好的抓一下ssh的报文,按理说我应该拿出RFC文档好好地的研读,但从以往的经历当中也没有遇到ssh的相关的大故障,最近在学习wireshark,那就用wireshark抓个包分析一下为什么ssh有时候为卡住?有的时候就会非常的顺畅?
# 操作系统是KALI LINUX
┌──(root💀kali)-[~]
└─# uname -a
Linux kali 5.14.0-kali4-amd64 #1 SMP Debian 5.14.16-1kali1 (2021-11-05) x86_64 GNU/Linux
┌──(root💀kali)-[~]
└─# cat /proc/version
Linux version 5.14.0-kali4-amd64 (devel@kali.org) (gcc-10 (Debian 10.3.0-12) 10.3.0, GNU ld (GNU Binutils for Debian) 2.37) #1 SMP Debian 5.14.16-1kali1 (2021-11-05)
- ssh客户端:192.168.80.100/24
- ssh服务端:192.168.80.128/24,网关:192.168.80.2 DNS:1.2.3.9(瞎编的)
下图是客户端登录时,在服务端抓的包:
如上图,从这个报文当中,我们可以看出来刚开始是三次握手,然后协商版本,而且还可以看到系统的发行版,紧接着就开始密钥交换相当交互,期间用到了diffle-helman这种密钥交换算法。
我们再向下看:
如上图所示,19号包和21号包是DNS查询,而且还不是一个普通的DNS正向查询,而是一个反向的PTR查询,从19号包来21来看一共发送了两次,第一次是在0.04秒左右的时候,没收到应答在5.05秒的时候又发送了一次,最的一次发送之后又等了9秒之后才继续向下交互,我们会发现这个时间消耗是比较大的,我们还可以更直观的把消耗的时间显示出来,ctrl+alt+6将wireshark的时间显示格式从“自捕获开始经过的秒数”调整为“自上一个显示分组经过的秒数”,如下所示,我们可以很直观看到确实在DNS的PTR查询时消耗了十几秒的时间,这个地方消耗时间,那客户端就会有一个十几秒的卡顿感。
我们继续看剩下的报文,如下所示,从剩下的报文当中我们没有再次看到有关于DNS的PTR查询记录,而客户端在输入密码之后也登录成功了,我们可以就此判断,服务端在两次DNS,PTR查询未果之后就放弃了DNS的PTR查询,继续下面的交互。
上述ssh卡住主要是DNS服务器没有回答,因为上述的DNS是1.2.1.2是故意瞎指的,根本都没有这台主机,那如果用真正的DNS服务器呢?下面我们就给服务器指一个真正的阿里的DNS服务器223.6.6.6,看看是什么现象?如下所示
从上图当中的时间来看(这里的时间显示格式是“从上一个显示的捕获分组”),223.6.6.6几乎是秒回了客户端的PTR查询,告诉客户端“no such name PTR”,还好DNS服务端有回应了,明确的告诉没有也好比没有响应,这让服务器“死了”PTR查询这条心,但我们还是可以看到ssh的服务端依然是查询了两次, 两次DNS服务器都有着“no such name”的响应。虽然没查询到,但ssh服务端与客户端的相互进程没怎么被耽搁,客户端的体验是非常的顺畅的,不会出现登录时卡顿的现象。
linux系统的ssh服务端是可以将DNS的PTR查询给关闭掉的:
# 将UseDNS 改成no之后,服务端就会再发送DNS的PTR查询了,这样登录起来就会比较快。
┌──(root💀kali)-[~]
└─# grep "UseDNS" /etc/ssh/sshd_config
#UseDNS no
UseDNS yes
还有一个有意思的发现,我用的系统是KALI LINUX官方做好的虚拟机,属于debian系列,里面已经安装了openssh,甚至vm-tools,/etc/ssh/sshd_config里面的UseDNS yes默认就是no关闭的,而centos系列的系统默认这个选项还是处于yes的状态,那这样不会变慢吗?并不会慢,我有多台阿里云的centos主机,UseDNS 都是处于Yes的状态,每次登录的时候ssh服务端都会发起查询,没关系呀,如果你DNS配置正确的话,每次DNS服务端都会很快的进行no such name的应答,并没有卡顿感,但如果你的DNS配置错误,那这个卡顿感就会很明显。
二、如果你在虚拟机当中把DNS设置成了网关
如果你在虚拟机当中把DNS设置成了网关的话,会发现网关会代替DNS对服务器进行应答回复,速度也是挺快的。
三、我们还可以自己搭建一个DNS试一下
视频当中有演示