排查SSH无法连接服务器一事
排查SSH无法连接服务器一事

排查SSH无法连接服务器一事

场景复现

在写这篇文章时,不仅感叹自己遇到的坑真是又麻烦、又坑人。好端端的服务器就连接不上了,问题神奇的就发生了。

问题发生过程为:通过SecureCRT连接服务器,提示:

Public Key Authentication Failed:
Public-key authentication with the server for user root failed.Please verify username and public/private key pair.

(翻译为:公钥认证失败:用户 root 与服务器的公钥身份验证失败。请验证用户名和公钥/私钥对。)

这时使用终端连接服务器,则提示:

fangjunyu@fangjunyudeMacBook-Pro ~ % ssh root@111.231.22.116
root@111.231.22.116: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

(翻译为:权限被拒绝(publickey、gssapi-keyex、gssapi-with-mic))

现在就开始我们的问题排查之旅。

环境配置

1、服务器版本:CentOS Linux release 7.9.2009 (Core)
SSH版本:OpenSSH_7.4p1, OpenSSL 1.0.2k-fips
2、客户端版本:macOS Monterey 12.7.3
SSH版本:OpenSSH_8.6p1, LibreSSL 3.3.6
3、客户端版本:macOS Sonoma 14.3.1
SSH版本:OpenSSH_9.4p1, LibreSSL 3.3.6

排查过程

大家可以看到,我有两台电脑,我一直使用这两台电脑连接远程机,在我发现老电脑(这里代指本次无法连接的问题机器)无法连接后,尝试使用新电脑进行连接。

是的,新电脑是可以连接到远程机的。

好了,我想可能是我老电脑的公钥和密钥出问题了,我可以把新电脑的公钥和密钥复制过来。

复制密钥

然后,我将新电脑的公钥、密钥打包,隔空投送给我的老电脑,并将老电脑的密钥打包备份。

注意:任何修改配置文件的操作都要备份,也可以通过下面的代码进行快速备份。

cp ~/.ssh/id_rsa{,backup} 
cp ~/.ssh/id_rsa.pub{,backup}

接着,完成SSH的替换,这时重新访问SecureCRT,提示我:

Enter Secure Shell Passphrase:
Enter a passphrase to decrypt your private key for root@111.231.22.116.
Comment: root@VM-16-16-centos
Passphrase

(翻译:输入密码以解密 root@111.231.22.116 的私钥)

如果输错密钥会提示:

Public Key Authentication Failed:
The passphrase is incorrect.Please reenter your passphrase.Letters in passphrase must be entered using the correct case.Make sure the Caps Lock key is not on.

(翻译:密码不正确。请重新输入密码。密码中的字母必须使用正确的大小写输入。请确保 Caps Lock 键未打开。)

密码输入成功,会提示:

Public Key Authentication Failed:
The server recognized your public key,/Users/fangjunyu/.ssh/id_rsa,but none of the known signature mechanisms were accepted. This normally means that the server you are connecting to does not comply with any of the supported standards.

(服务器识别了您的公钥/Users/fangjunyu/.ssh/id_rsa,但没有接受任何已知的签名机制。这通常意味着您正在连接的服务器不符合任何支持的标准。)

复制密钥后,问题仍然没有任何解决。

另外,在输入私钥密码的过程中,SecureCRT有提示我选择对应的公钥,但是在复现过程中,没有再次弹出选择公钥的窗口,在这里做一个备注。

也弹出过:

Public Key Authentication Failed:
Public-key authentication with the server for user root failed.Please verify username and public/private key pair.

(翻译:用户 root 与服务器的公钥身份验证失败, 请验证用户名和公钥/私钥对)

这个问题复现中也没有出现,可能是连接的用户名输入错了导致的。

匹配公钥和私钥

接着,我把老电脑的公钥和私钥还原回去,并进行下一步的排查。

还原老电脑的密钥后,我在想,是不是我的公钥和密钥不匹配导致的。

虽然我尝试使用新电脑连接服务器,并在服务器中查看id_rsa.pub文件的指纹。

[root@fangjunyu]~# ssh-keygen -l -f ~/.ssh/id_rsa.pub 
2048 SHA256:UpaDYjtc5pcjAm/Ojym5m/LuabmGpkn+qL4k3N6to7g root@fangjunyu.com (RSA)

这时我再查看老电脑的密钥指纹,发现老电脑的密钥指纹完全一样:

ssh-keygen -l -f /Users/fangjunyu/.ssh/id_rsa    
2048 SHA256:UpaDYjtc5pcjAm/Ojym5m/LuabmGpkn+qL4k3N6to7g root@fangjunyu.com (RSA)
ssh-keygen -l -f /Users/fangjunyu/.ssh/id_rsa.pub
2048 SHA256:UpaDYjtc5pcjAm/Ojym5m/LuabmGpkn+qL4k3N6to7g root@fangjunyu.com (RSA)

然后我又用新电脑查看密钥指纹,发现新电脑的密钥指纹反而是与服务器、老电脑的密钥指纹对不上:

ssh-keygen -l -f ~/.ssh/id_rsa 
2048 SHA256:UpaDYjtc5pcjAm/Ojym5m/LuabmGpkn+qL4k3N6to7g /Users/fangjunyu/.ssh/id_rsa.pub (RSA)
ssh-keygen -l -f ~/.ssh/id_rsa.pub 
2048 SHA256:UpaDYjtc5pcjAm/Ojym5m/LuabmGpkn+qL4k3N6to7g no comment (RSA)

这是一件很神奇的事情,密钥不一致可以登录,密钥一致反而登录不上。

然后我又通过排查发现服务器端的~/.ssh/authorized_keys,配置了新电脑的公钥,因此才解释了为什么新电脑的公钥可以连接服务器,但是老电脑的公钥就没有连接服务器。

[root@fangjunyu]~# cat ~/.ssh/authorized_keys  
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuEgwLPXmoAEki73WjTBOGfEl6gyMoAXW/fCB40gq/5U54U1e9GRX6TgusBmKyP5q6kFrqqNTE5z4n37hwKzKHbgUmMz2dipEzahCJDFxoDmr1C1XRAQNEWX+ECKYD7eGMRy5e7P9qwLb6q376CEN/FTamy4KO6JAcCe17POD2j+oUCAp2ymuGJsh2BdbgBZ6P4kpEHHY3QTP2um0txVswiTk2G/wejWyMuYtQ+zI/Az26BJZ2Ilv6YBObZrP7XcdwhK86IypBn0LwyP8RKSodLdmjCIFAROexX9fblAK1tcUvUUk4CW15ON8uI/cdUzwekUca45jKyKPSV4kBiUzz root@VM-16-16-centos

随后,我把老电脑的公钥也添加到服务器的~/.ssh/authorized_keys,或者说,是把服务器的~/.ssh/id_rsa.pub内容追加到~/.ssh/authorized_keys文件中,问题才得以解决,这是旧电脑也能连接到服务器了。

内容追加代码:

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

这时,再使用老电脑连接服务器,就发现可以连接了。

问题解决了,这是本次教程的一个里程碑,标志是问题找到了解决方案。

———————— 下面是后续的排查工作——————-

但是排查工作没有结束,为什么id_rsa公钥会连接不上,反而需要通过配置authorized_key文件才可以连接。

接着,我开始检查密钥私钥文件是不是损坏了,然后使用SSH工具检查:

openssl rsa -check -in /path/to/private_key

执行后,输出如下:

openssl rsa -check -in ~/.ssh/id_rsa 
Enter pass phrase for /Users/fangjunyu/.ssh/id_rsa:
RSA key ok
writing RSA key

这表示显示 RSA 密钥是有效的,并且写入了 RSA 密钥。同时表明私钥文件 ~/.ssh/id_rsa 在格式上是有效的,并且没有检测到明显的问题。

升级SSH版本

经过一番深思熟虑的对比,发现老电脑的ssh版本比较低:

1、客户端版本:macOS Monterey 12.7.3
SSH版本:OpenSSH_8.6p1, LibreSSL 3.3.6
2、客户端版本:macOS Sonoma 14.3.1
SSH版本:OpenSSH_9.4p1, LibreSSL 3.3.6

这里可以看到开头场景配置中,关于SSH版本的配置。老电脑的版本为:

ssh -V
OpenSSH_8.6p1, LibreSSL 3.3.6

因此,怀疑是SSH版本的问题,我们开始升级SSH来排查是否能够解决。

首先,我们使用Homebrew升级OpenSSH:

brew upgrade openssh

我在执行brew upgrade openssh过程中,发现openssh没有安装,报了如下问题:

ssh -V
OpenSSH_8.6p1, LibreSSL 3.3.6
fangjunyu@fangjunyudeMacBook-Pro .ssh % brew upgrade openssh

==> Downloading https://formulae.brew.sh/api/formula.jws.json
######################################################################### 100.0%
==> Downloading https://formulae.brew.sh/api/cask.jws.json
######################################################################### 100.0%
Error: openssh not installed

然后我们执行下面的代码进行openssh的安装和升级:

brew install openssh
brew upgrade openssh

安装并升级完成后,运行 ssh -V 命令查看OpenSSH有无升级完成。

ssh -V
OpenSSH_8.6p1, LibreSSL 3.3.6

brew upgrade openssh
Warning: openssh 9.7p1 already installed

ssh -V              
OpenSSH_8.6p1, LibreSSL 3.3.6

我们可以看到,安装完成后,版本号还是旧的,但是执行升级命令,则提示已经是最新的版本。

这个问题是路径造成的,我们先确认路径:

which ssh

获得ssh路径为:

/usr/local/bin/ssh

然后,我们在shell配置文件中配置系统路径:配置文件有:~/.bash_profile、~/.bashrc

因为我是用的是zsh,因此我在 ~/.zshrc 文件中配置了这一路径,然后执行下述命令配置系统路径:

SSH_PATH=$(which ssh) \
&& echo "export PATH=\"$SSH_PATH:\$PATH\"" >> .zshrc \
&& source .zshrc

执行完成后,再次执行ssh -V命令,就显示最新的ssh版本了。

ssh -V
OpenSSH_9.7p1, OpenSSL 3.2.1 30 Jan 2024

然后我重新尝试连接服务器,仍然是前面的报错,这表示升级SSH版本这条路走不通。

修改文件权限

检查本地密钥文件(例如 id_rsa)的权限是否正确,它们应该只对所有者有读写权限(600)。错误的权限设置可能导致密钥被拒绝。

根据这一问题,我开始检查本地的密钥权限是否有变动导致的:

ls -al ~/.ssh/id_rsa*  
-rw-------@ 1 fangjunyu  staff  1766  3 25 15:37 /Users/fangjunyu/.ssh/id_rsa
-rw-------@ 1 fangjunyu  staff   400  3 25 15:39 /Users/fangjunyu/.ssh/id_rsa.pub

发现老电脑的配置文件权限没有改动,因此也不是密钥权限的问题。

虚拟机测试

现在又开始怀疑老电脑的配置环境有问题,接着我把id_rsa和id_rsa.pub复制到我VMware Fusion虚拟机内,然后执行:

ssh % ssh root@111.231.22.116           
root@111.231.22.116: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

但是在服务器端执行:

cat id_rsa.pub >> authorized_keys

虚拟机现在也能够连接上服务器了。

这个测试表示并不是老电脑和虚拟机环境的配置,大概率问题还是出在密钥或服务器的公钥上。

虽然,我前面有使用 sha256sum和来校验服务器和老电脑的文件,都是一样的,但还不能排除这个问题,因此我先更换服务器的公钥来判断这个问题。

更换服务器公钥

这里,我是用新电脑连接服务器并执行:

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

前面已经提到了,执行后,我的老电脑也可以使用ssh连接服务器。

接着,我在老电脑上执行:

scp ~/.ssh/id_rsa.pub [用户名]@主机名+地址

具体输出如下:

scp ~/.ssh/id_rsa.pub root@111.231.22.116:/root/.ssh/
id_rsa.pub         100%  400    15.2KB/s   00:00  

这样id_rsa.pub文件,就从服务器端传输成功了。然后我再将服务器上新追加的公钥删掉掉。

然后,重新登录服务器,现在老电脑又登不上了。

现在得出的结论是,跟公钥文件没有关系,不是服务器的公钥文件有损坏。另外注意修改id_rsa.pub文件时,也要做一下备份。

未完结的结论

最后,查询了很多教程,最后得出的结论是,客户端的密钥生成id_rsa.pub文件后,不需要传输到服务器上。而是将id_rsa.pub文件内容放到前面提到的~/.ssh/authorized_keys,就可以,所以前面一直有这样的一个误区。

至于,为什么突然之间,老电脑无法连接到服务器,可能是authorized_keys被修改/调整了。但我实际排查的时候,并没有发现authorized_keys有修改的痕迹,或许是我的一个误操作导致的。

该问题暂定定性为:authorized_keys被修改导致无法连接服务器。

其他知识

多个密钥认证

在使用SSH连接服务器时,我们可以执行:

ssh -vvv user@host

这个命令表示SSH连接时,会尝试使用多个密钥进行认证。

工作流程为:

  • 客户端列出了它的可用身份验证密钥(identity files),
  • 客户端尝试通过这些密钥进行身份验证。
  • 最后,客户端尝试了所有可用密钥后,连接成功,或者因为没有更多的身份验证方法可尝试,因此连接被拒绝。

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注