排查常见SSH 'Permission Denied'错误与连接问题

掌握SSH连接技巧,攻克'Permission denied'错误。本指南详细介绍了如何使用详细模式(`-vvv`)诊断认证失败、修复服务器端`.ssh`目录的关键文件权限(`700`/`600`),以及验证`sshd_config`中必要的服务器配置设置,以实现可靠的远程访问。

排查常见SSH 'Permission Denied'错误与连接问题

SSH Permission denied 错误通常意味着服务器可达,但拒绝验证您的身份。这与 Connection timed outConnection refusedNo route to host 不同。将所有问题都视为“SSH故障”会浪费时间,因此首先要区分认证失败和网络故障。

使用详细日志运行失败的命令:

ssh -vvv user@remote_host

您需要寻找清晰的线索:客户端使用了哪个用户名、提供了哪些密钥文件、服务器是否接受了任何密钥,以及还有哪些认证方法可用。以下大多数修复方法都基于将这些线索与服务器端状态匹配。

理解SSH认证流程

当您尝试连接时,服务器只允许其配置中启用的认证方法。典型的服务器首先尝试公钥认证,之后可能允许密码认证,具体取决于策略:

  1. 公钥认证: 客户端提供公钥,服务器检查对应的私钥是否有效且与授权密钥(authorized_keys 文件)匹配。
  2. 密码认证: 如果密钥认证失败或禁用,服务器会提示输入密码。

当您收到 Permission denied 时,TCP连接已建立。服务器只是不接受您为该用户提供的凭据。

诊断连接问题:详细模式的力量

诊断SSH问题最有效的单一工具是以详细模式运行客户端。通过添加 -v-vv-vvv 标志,客户端会输出关于协商过程的详细调试信息。

使用详细标志

使用以下命令结构:

ssh -vvv user@remote_host

在输出中查找的内容:

  • 用户名: 查找 Authenticating to ... as 'user'。错误的Linux用户名是最容易忽略的错误之一。
  • 提供的密钥: 查找 Offering public key。如果预期的密钥从未出现,请修复客户端配置。
  • 服务器响应: 如果每个提供的密钥后都跟着 Authentications that can continue,则表示服务器拒绝了这些密钥。
  • 认证方法: 如果未列出 publickey,则服务器可能不允许该账户或主机块使用密钥认证。

解决 Permission denied (publickey)

此错误明确表示服务器拒绝了提供的公钥凭据。修复方法通常在于权限或密钥配对。

1. 检查密钥文件权限(客户端)

出于安全考虑,SSH客户端对您的私钥文件(例如 ~/.ssh/id_rsa)的权限非常严格。如果这些文件权限过于开放,客户端将拒绝使用它们。

确保您的私钥仅对您可读:

chmod 600 ~/.ssh/id_rsa

2. 验证密钥存在并使用正确的密钥

确保您使用正确的身份文件进行连接,尤其是在使用非标准密钥或多个密钥对时。

使用 -i 标志指定正确的私钥:

ssh -i /path/to/your/specific_private_key user@remote_host

如果您的代理加载了多个密钥,请为此测试添加 IdentitiesOnly=yes

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

3. 服务器端权限和所有权

这是密钥认证失败最常见的原因。SSH对服务器上您要登录的用户强制执行严格的目录和文件权限。

服务器上的路径 所需权限 所有者
~/.ssh 目录 700 (rwx------) 用户
~/.ssh/authorized_keys 文件 600 (rw-------) 用户

通过控制台、云串行控制台、密码认证或其他管理员账户登录,并以目标用户身份或使用正确路径运行以下命令:

# 设置目录权限
chmod 700 ~/.ssh

# 设置 authorized_keys 权限
chmod 600 ~/.ssh/authorized_keys

# 验证所有权(将 'myuser' 替换为实际用户名)
chown -R myuser:myuser ~/.ssh

如果用户的主目录对组或其他用户可写,当 StrictModes 启用时,OpenSSH 也可能拒绝密钥。使用以下命令检查:

ls -ld ~ ~/.ssh ~/.ssh/authorized_keys

对于大多数普通用户主目录,755 或更严格即可。

4. 确认密钥已实际添加

确保客户端的公钥与粘贴到服务器 ~/.ssh/authorized_keys 文件中的内容匹配。缺少字符、换行或复制了私钥都会导致认证失败。

如果密码访问仍然可用,添加密钥时请使用 ssh-copy-id

ssh-copy-id user@remote_host

排查配置文件问题 (sshd_config)

如果密钥和权限都正确,问题通常出在SSH守护进程配置文件中,该文件通常位于服务器的 /etc/ssh/sshd_config

1. 检查认证方法

确保明确允许公钥认证。

配置检查: 查找以下行,确保它们未被注释(#)且设置正确:

PubkeyAuthentication yes
AuthorizedKeysFile  .ssh/authorized_keys

同时检查文件底部附近的 Match 块。全局设置可能允许公钥,但后面的 Match UserMatch GroupMatch Address 块可能会为您正在测试的确切登录禁用它们。

2. 密码认证状态

如果您临时依赖密码登录,请验证其已启用。如果设置为 no,则必须使用密钥。

PasswordAuthentication yes

3. PermitRootLogin

如果您尝试以 root 身份登录,请确保允许此操作。最佳实践通常是使用普通用户登录并使用 sudo,但为了排查问题,您可以检查此设置:

PermitRootLogin prohibit-password

对于root登录,许多系统默认仅允许密钥访问或完全禁用root登录。建议使用具有 sudo 权限的普通用户。如果必须更改SSH守护进程设置,请在重新加载前验证语法:

sudo sshd -t
sudo systemctl reload sshd  # 某些系统使用:sudo systemctl reload ssh

其他常见连接错误

虽然密钥问题是主要原因,但其他错误也可能阻止访问:

A. 连接超时

这通常意味着客户端根本无法到达服务器,表明是网络问题,而非认证问题。

可能的原因:

  • 服务器宕机或不可达。
  • 防火墙(本地或网络)阻止了端口22(或自定义SSH端口)的连接。
  • IP地址或主机名错误。

使用 ping 进行基本可达性检查,使用 nc 检查SSH端口:

nc -vz remote_host 22

B. 无路由到主机

与超时类似,这是网络基础设施问题。客户端找不到通往服务器IP地址的路径。检查路由表、VPN状态,或确保远程服务器有有效的网络接口处于活动状态。

C. 服务器拒绝我们的密钥

如果详细输出显示服务器正在主动拒绝密钥,但您已验证了 authorized_keys 文件,请检查服务器上的SELinux或AppArmor安全上下文。这些安全模块可以覆盖文件权限,并在上下文不正确时阻止SSH访问。

通常有效的实用顺序

首先检查用户名。然后使用 ssh -o IdentitiesOnly=yes -i ... 强制使用您预期的密钥。如果客户端提供了正确的密钥但服务器拒绝,请检查服务器上的 authorized_keys、所有权和权限。如果密钥从未被提供,请修复本地的 ~/.ssh/config、代理或密钥路径。如果连接从未到达认证阶段,请转而进行网络排查,而不是更改密钥文件。