SSH 密钥登录失败时,先看这几处

2026-09-26 约 1100 字 SSH

公钥认证失败通常不会给出明确原因,客户端只是一句 Permission denied (publickey)。下面这套顺序是从最常见的几类原因排下来的, 大部分情况能在前两步解决。

第一步:把失败点定位到具体环节

在客户端加 -v,看日志里发送了哪把密钥、服务端接受还是拒绝:

ssh -v user@host

关注这几行:

debug1: Offering public key: ~/.ssh/id_ed25519
debug1: Authentications that can continue: publickey
debug1: No more authentication methods to try.

如果出现了 Offering 却被拒绝,说明密钥发出去了但服务端不认; 如果根本没出现 Offering,是本地没有可用密钥,或者 IdentitiesOnly / agent 的问题。

第二步:检查服务端权限

sshd 对权限很严格:家目录、~/.ssh、 authorized_keys 都不能对组和其他用户可写, 否则该文件会被直接忽略。

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod g-w,o-w ~   # 家目录不能对 group/other 可写

用 ls -ld 一眼看出问题:

ls -ld ~ ~/.ssh ~/.ssh/authorized_keys
# 期望类似
# drwx------ user user  ~
# drwx------ user user  ~/.ssh
# -rw------- user user  ~/.ssh/authorized_keys

属主也要对。如果 authorized_keys 属于 root 而登录用户是别人, 同样会被拒绝。

第三步:确认服务端真的启用了密钥登录

配置文件里写了什么不算数,要看解析后的生效值:

sudo sshd -T | grep -Ei 'pubkey|password|authorizedkeysfile|permitrootlogin'

重点看 authorizedkeysfile。默认是 .ssh/authorized_keys .ssh/authorized_keys2, 但有些发行版或加固脚本会改成别的路径(比如集中放到 /etc/ssh/keys/%u), 这时你放在 ~/.ssh/authorized_keys 的内容就不会被读取。

提醒 改完 sshd_config 要 sshd -t 校验再 reload。 改错了直接重启可能导致再也登不上,尤其是只开了密钥认证的机器。

第四步:Windows OpenSSH 的额外要求

在 Windows 上用 OpenSSH Server 时,如果登录账户属于管理员组, 密钥文件不是 ~/.ssh/authorized_keys,而是:

C:\ProgramData\ssh\administrators_authorized_keys

并且它对 ACL 有硬性要求:只能有 Administrators 和 SYSTEM 有权限。 用 icacls 设置:

icacls C:\ProgramData\ssh\administrators_authorized_keys `
  /inheritance:r `
  /grant "Administrators:F" `
  /grant "SYSTEM:F"

这一步非常容易漏。文件内容和格式都对、权限看起来也没问题, 但只要继承了别的 ACE,sshd 就会静默忽略整个文件,表现就是「密钥明明放对了却登不上」。 判断方法:把客户端 -v 打开,服务端同时看 OpenSSH 日志 (事件查看器 → 应用程序和服务日志 → OpenSSH → Operational), 里面会明确写 Authentication refused: bad ownership or modes 之类的信息。

第五步:编码与换行

把公钥拷贝过去时最容易出问题的是换行。Windows 记事本存成 CRLF, 或复制时带上了多余的空格,都会让 sshd 解析失败。

# 检查是否存在 CR
grep -c $'\r' ~/.ssh/authorized_keys

# 清理并确保只有一行
sed -i 's/\r$//' ~/.ssh/authorized_keys

也可以用 ssh-copy-id 让它自己处理,比手工复制可靠:

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host

排查清单

现象 大概率原因
完全没有 Offering 行 本地无密钥 / agent 未加载 / 指定了错误的 IdentityFile
Offering 之后被拒 服务端权限、属主、authorizedkeysfile 路径
只有 root 能登、普通用户不行 AllowUsers / AllowGroups 限制
Windows 上密钥放对仍失败 administrators_authorized_keys 的 ACL
同样的密钥昨天能用今天不行 家目录被改过权限,或密钥文件被重启脚本覆盖
← 返回笔记列表 下一篇:写一个可靠的自启服务单元 →