排查常见SSH 'Permission Denied'错误与连接问题
掌握SSH连接技巧,攻克'Permission denied'错误。本指南详细介绍了如何使用详细模式(`-vvv`)诊断认证失败、修复服务器端`.ssh`目录的关键文件权限(`700`/`600`),以及验证`sshd_config`中必要的服务器配置设置,以实现可靠的远程访问。
排查常见SSH 'Permission Denied'错误与连接问题
SSH Permission denied 错误通常意味着服务器可达,但拒绝验证您的身份。这与 Connection timed out、Connection refused 或 No route to host 不同。将所有问题都视为“SSH故障”会浪费时间,因此首先要区分认证失败和网络故障。
使用详细日志运行失败的命令:
ssh -vvv user@remote_host
您需要寻找清晰的线索:客户端使用了哪个用户名、提供了哪些密钥文件、服务器是否接受了任何密钥,以及还有哪些认证方法可用。以下大多数修复方法都基于将这些线索与服务器端状态匹配。
理解SSH认证流程
当您尝试连接时,服务器只允许其配置中启用的认证方法。典型的服务器首先尝试公钥认证,之后可能允许密码认证,具体取决于策略:
- 公钥认证: 客户端提供公钥,服务器检查对应的私钥是否有效且与授权密钥(
authorized_keys文件)匹配。 - 密码认证: 如果密钥认证失败或禁用,服务器会提示输入密码。
当您收到 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 User、Match Group 或 Match 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、代理或密钥路径。如果连接从未到达认证阶段,请转而进行网络排查,而不是更改密钥文件。