我的远程Linux主机的操作系统是Ubuntu 24。
按照网上的教程,我在Git Bash上使用私钥文件成功ssh登录远程Linux主机,命令如下所示:
$ ssh [email protected] -i .ssh/id_rsa
但是使用同样的命令和私钥文件,却无法在XShell上ssh登录远程Linux主机,报错“所选的用户秘钥未在远程主机上注册。请再试一次”。
查看ssh的日志文件/var/log/auth.log,我发现如下信息:
userauth_pubkey: signature algorithm ssh-rsa not in PubkeyAcceptedAlgorithms [preauth]
这表明远程主机的 SSH 服务在进行公钥认证时,发现客户端使用的公钥签名算法是 ssh-rsa,但是在远程主机的配置中,ssh-rsa算法被禁用了,因此认证失败。
在Git Bash 中使用私钥可以登录成功,可能是因为 Git Bash 使用的是较新的 OpenSSH 客户端版本,并能够使用备用的签名算法(如 rsa-sha2-256 或 rsa-sha2-512)。但是在 XShell 中,可能由于其默认配置或旧版本的客户端,它仍然依赖于 ssh-rsa 签名算法进行身份验证,导致认证失败。
从 OpenSSH 8.8 开始,ssh-rsa 算法被视为不再安全,部分服务器配置(例如Ubuntu 24)默认禁用了该算法。在远程主机的 SSH 服务中,可能已经通过 PubkeyAcceptedAlgorithms 配置来禁用 ssh-rsa 算法,而只接受更安全的算法,例如 rsa-sha2-256 或 rsa-sha2-512。 查看我的远程Linux主机的OpenSSH版本:
$ sshd -V
OpenSSH_9.6p1 Ubuntu-3ubuntu13.5, OpenSSL 3.0.13 30 Jan 2024
发现是OpenSSH 9.6版本。
OpenSSH 9.6版本支持更安全的ECDSA(Elliptic Curve Digital Signature Algorithm) 算法生成的公钥和私钥。因此我解决XShell问题的方法是,使用ECDSA算法重新生成一对公钥和私钥,可以使用XShell的“工具(T)”->“新建用户秘钥生成向导”来做到:
另一个解决方案是,允许 ssh-rsa 算法(如果远程主机允许)。如果你有对远程主机的控制权,可以通过修改远程主机的 SSH 配置文件 /etc/ssh/sshd_config 来允许 ssh-rsa 算法。打开 /etc/ssh/sshd_config 文件:
sudo vim /etc/ssh/sshd_config
查找并添加(或修改)以下行,允许 ssh-rsa 算法:
PubkeyAcceptedAlgorithms +ssh-rsa
重启 SSH 服务:
sudo systemctl restart ssh
# 如果你的系统是CentOS
sudo systemctl restart sshd
其他会引起“所选的用户秘钥未在远程主机上注册。请再试一次”或“服务器拒绝了用户密钥”问题的原因还有:
1 没有正确设置目录和文件的权限:
chmod 700 .ssh
chmod 600 .ssh/authorized_keys
并且authorized_keys文件要归属于用户组,例如:
chown ubuntu:ubuntu .ssh/uthorized_keys
2 密钥错误:服务器上的 authorized_keys 保存的应是公钥(一般以.pub作为文件后缀名),而不是私钥。
3 未开启密钥验证:/etc/ssh/sshd_config这个配置文件中应有 PubkeyAuthentication yes 这一行,且没有被注释掉
4 用户名和密钥不匹配:假设密钥是放在 /home/debian/.ssh/ 下(即用户是 debian),但是登录的用户名却使用ubuntu
5 root用户名被禁止登陆:假设etc/ssh/sshd_config 配置了 PermitRootLogin no,却用 root 账户来登录
6 开启了SELinux:使用getenforce命令查看SELinux的状态,状态应该是Permissive,不能是 Enforcing。临时关闭SELinux:
setenforce 0
永久关闭SELinux的方法是:编辑/etc/sysconfig/selinux配置文件,把其中的 SELINUX=enforcing 替换为 SELINUX=disabled
7 SSH 配置文件/etc/ssh/sshd_config中有这么一行:
# AuthorizedKeysFile .ssh/authorized_keys
而你的.ssh目录下的对应文件的名字却是authorized_key,应该是authorized_keys。