排查 SSH 权限拒绝(公钥)问题

使用 SSH 时遇到“权限被拒绝(公钥)”错误?本指南提供了全面的步骤来解决这一常见的身份验证错误。学习如何仔细验证 SSH 密钥对,诊断客户端和服务器上错误的文件权限,并确保 `authorized_keys` 文件配置正确。通过实际示例和逐步说明,您将重新获得对远程系统的安全访问。

排查 SSH 权限拒绝(公钥)问题

Permission denied (publickey) 表示服务器可达,但未接受您尝试的用户进行的任何公钥身份验证尝试。这缩小了问题范围。您不再需要调试路由、DNS 或 SSH 端口是否开放。您需要调试的是身份:用户名、客户端提供的私钥、服务器上存储的公钥以及决定是否允许登录的服务器规则。

最快速的实用命令是:

ssh -vvv user@your_server_ip

查找 Authenticating to ... as 'user',然后查找 Offering public key。如果未提供预期的密钥,请修复客户端。如果提供了预期的密钥但被拒绝,请修复服务器端的 authorized_keys、所有权、权限或 SSH 守护进程策略。

“权限被拒绝(公钥)”的常见原因

“权限被拒绝(公钥)”错误可能由多种配置问题引起。识别根本原因通常需要系统地检查以下组件:

  • 文件权限不正确: SSH 出于安全原因对文件和目录权限非常敏感。本地 ~/.ssh 目录、私钥文件或服务器端的 ~/.ssh 目录和 authorized_keys 文件权限不正确可能会阻止身份验证。
  • authorized_keys 条目缺失或不正确: 服务器的 authorized_keys 文件必须包含您尝试登录用户的正确公钥。如果密钥缺失、格式错误或与错误的用户关联,身份验证将失败。
  • 密钥对关联不正确: 您的 SSH 客户端可能提供了错误的私钥,或者服务器可能没有在 authorized_keys 文件中列出相应的公钥。
  • SSH 代理问题: 如果您使用 SSH 代理,它可能未正确加载您的私钥,或者配置不正确。
  • 服务器端 SSH 配置: 虽然对于此特定错误不太常见,但服务器的 SSH 守护进程配置(sshd_config)可能对公钥身份验证有特定限制。

逐步故障排除指南

让我们深入探讨诊断和修复这些问题的实际步骤。

1. 验证本地私钥和权限

您的本地 SSH 配置是首先要检查的地方。确保您的私钥可访问且具有正确的权限。

检查私钥是否存在

您的私钥通常位于 ~/.ssh/id_ed25519~/.ssh/id_rsa,但许多团队使用项目特定的名称。列出您的密钥:

ls -la ~/.ssh

不要将私钥上传或粘贴到 authorized_keys 中。服务器需要 .pub 文件的内容,而不是私钥。

验证本地文件权限

~/.ssh 目录和您的私钥文件应具有限制性权限以防止未经授权的访问。

  • ~/.ssh 目录: 应为 700 (drwx------)。
  • 私钥文件(例如 id_rsa): 应为 600 (-rw-------)。

使用 chmod 命令设置正确的权限:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa

提示:如果您使用不同的密钥名称,请将 id_rsa 替换为您的实际私钥文件名。

如果您要测试特定密钥,请强制使用它:

ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_prod user@your_server_ip

这可以防止您的代理首先提供一长串不相关的密钥。

2. 验证服务器端 authorized_keys 配置

这通常是最常见的罪魁祸首。服务器必须为您的尝试身份验证的用户正确列出您的公钥。

访问服务器(如果可能)

如果您仍然可以通过其他方法(例如密码身份验证、其他用户帐户或控制台)访问服务器,请登录以检查 authorized_keys 文件。

检查 authorized_keys 文件位置

authorized_keys 文件通常位于您尝试登录的用户的主目录中的 ~/.ssh/authorized_keys

验证服务器端文件权限

与客户端类似,服务器端权限至关重要:

  • 服务器上的 ~/.ssh 目录: 应为 700 (drwx------)。
  • 服务器上的 authorized_keys 文件: 应为 600 (-rw-------)。

确保在服务器上正确设置了这些权限:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

还要验证所有权。.ssh 目录和 authorized_keys 文件通常应属于您登录的帐户:

chown -R youruser:youruser ~/.ssh
ls -ld ~ ~/.ssh ~/.ssh/authorized_keys

如果在 sshd_config 中启用了 StrictModes,当主目录或 .ssh 路径可被错误用户写入时,OpenSSH 可能会拒绝密钥。

验证 authorized_keys 内容

使用文本编辑器(例如 nanovim)打开 ~/.ssh/authorized_keys 文件。每个公钥应单独占一行。确保您期望使用的公钥存在且格式正确。它应以 ssh-rsassh-ed25519 或类似开头,后跟一长串字符,并可选择性地跟一个注释。

示例 authorized_keys 条目:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQD... your_public_key_string user@hostname

不要将您的私钥添加到 authorized_keys。此处只应包含公钥。

3. 确保添加了正确的公钥

可能复制了错误的公钥,或者服务器上的公钥与您的本地私钥不匹配。

检索您的本地公钥

您的公钥是您私钥的对应部分。您可以使用 ssh-keygen 命令查看它:

cat ~/.ssh/id_rsa.pub

此命令将输出您的公钥。将此输出与服务器的 ~/.ssh/authorized_keys 文件中的条目仔细比较。即使是一个拼写错误或缺少字符也会导致身份验证失败。

为了更清晰的比较,打印从您尝试使用的私钥派生的公钥:

ssh-keygen -y -f ~/.ssh/id_ed25519_prod

该输出应与远程用户的 authorized_keys 中的一行匹配。

提示:如果您对服务器有密码访问权限,使用 ssh-copy-id 是添加公钥的快速方法。

ssh-copy-id user@your_server_ip

此命令会自动将您的默认公钥(~/.ssh/id_rsa.pub)附加到远程服务器上的 ~/.ssh/authorized_keys 文件,并设置正确的权限。

4. 指定正确的私钥(如果不是默认)

如果您使用非默认私钥(例如 ~/.ssh/my_other_key),您需要告诉您的 SSH 客户端使用哪个密钥。

使用 -i 标志

您可以使用 -i 选项指定身份文件(私钥):

ssh -i ~/.ssh/my_other_key user@your_server_ip
配置 ~/.ssh/config

为方便起见,您可以配置 SSH 客户端,使其始终对给定主机使用特定密钥:

在本地机器上创建或编辑 ~/.ssh/config 文件,并添加如下条目:

Host your_server_alias
  HostName your_server_ip_or_domain
  User your_username
  IdentityFile ~/.ssh/my_other_key
  IdentitiesOnly yes

然后您只需使用以下命令即可连接:

ssh your_server_alias

5. 检查 SSH 代理状态

如果您依赖 SSH 代理来管理您的密钥,请确保它正在运行并且已加载您的密钥。

检查代理是否正在运行
echo "$SSH_AUTH_SOCK"

如果输出一个路径,则代理可能正在运行。如果为空,您可能需要启动一个。

向代理添加密钥

如果您的密钥未加载,请添加它:

ssh-add ~/.ssh/id_rsa

如果提示输入密码,请输入。您可以使用 ssh-add -l 验证添加了哪些密钥。

如果 ssh-add -l 显示许多不相关的密钥,并且服务器在多次尝试后断开连接,请从代理中删除旧密钥,或对该主机使用 IdentitiesOnly yes

6. 使用详细模式进行调试

SSH 有一个详细模式(-v-vv-vvv 用于更详细的级别),可以提供有关身份验证过程失败位置的宝贵线索。

ssh -vvv user@your_server_ip

检查输出中与密钥身份验证、提供密钥和服务器响应相关的消息。这通常直接指向问题所在。

指示公钥失败的详细输出示例:

debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
debug1: Trying private key: /home/user/.ssh/id_rsa
debug1: read PEM private key file /home/user/.ssh/id_rsa
debug1: failed to use sshkey: /home/user/.ssh/id_rsa
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: password

此输出意味着客户端尝试了 id_rsa,服务器未接受它,客户端继续使用下一个允许的方法。

7. 服务器端 sshd_config 审查(高级)

检查 /etc/ssh/sshd_config 以及 /etc/ssh/sshd_config.d/ 中的任何文件。确认公钥身份验证已启用:

PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

然后查找文件底部附近的 Match 块。后面的 Match UserMatch GroupMatch Address 块可能会覆盖您正在测试的确切帐户的早期设置。

进行任何更改后,在重新加载之前验证语法:

sudo sshd -t
sudo systemctl reload sshd

某些系统使用 ssh 作为服务名称而不是 sshd

可靠的故障排除顺序

使用详细输出来避免猜测。首先确认用户名。然后确认客户端提供了您期望的私钥。然后确认匹配的公钥位于目标用户的 authorized_keys 中。然后检查所有权和权限。只有在这些都干净之后,才应该花时间在 sshd_configMatch 块、SELinux 上下文或帐户限制上。

该顺序解决了大多数 Permission denied (publickey) 情况,无需随机更改,并且可以防止您为了获得一个紧急登录而削弱 SSH 安全性。