加载中...
SSH 公钥认证排查报告
发表于:2026-10-21 | 分类: ssh
字数统计: 2.2k | 阅读时长: 7分钟 | 阅读量:

SSH 公钥认证排查报告

一、问题背景

使用 ssh -i <私钥文件> 连接远程服务器时,出现两个疑问:

  1. 公钥已经放进服务器的 authorized_keys,为什么登录还要求 Enter passphrase for key?
  2. 输入 passphrase 之后,为什么仍然退回到要求输入服务器登录密码?

二、关键概念:两个”密码”是两回事

SSH 密钥认证里有两道独立的关卡,容易被混淆:

提示 含义 验证位置 与 authorized_keys 的关系
Enter passphrase for key 解锁本地加密私钥的密码 本地机器 无关
xxx's password 服务器账号登录密码 远程服务器 公钥认证失败后才回退到它
  • passphrase:保护本地私钥文件的密码,只在本地验证,不会发送到服务器。只要私钥文件在生成时设置了加密,每次使用都会要求输入。
  • 公钥是否在 authorized_keys:决定服务器认不认这把钥匙,和私钥本身是否加密没有任何关系。

认证流程:

  1. 本地:输入 passphrase 解密私钥;
  2. 客户端:用私钥对挑战做签名,把公钥发给服务器;
  3. 远程:服务器在 authorized_keys 中查找该公钥并验证签名。

任意一步失败,都会回退到密码登录。


三、为什么会要求输入 passphrase(即使公钥已就位)

因为私钥文件在生成时被加密了。SSH 必须先用 passphrase 解密私钥,才能用它做签名。这是加密私钥的正常行为,不是配置错误,也与公钥是否在 authorized_keys 无关。

确认私钥是否加密

head -n 3 <私钥文件>

出现 Proc-Type: 4,ENCRYPTED 或解析时要求密码,即为加密私钥。

避免每次都输入 passphrase

# 推荐:用 ssh-agent 缓存,私钥仍保持加密
eval "$(ssh-agent -s)"
ssh-add <私钥文件>        # 输入一次,本次会话内免输

# 不推荐:彻底去掉 passphrase(安全性下降)
ssh-keygen -p -f <私钥文件>   # 旧密码验证后,新密码留空

四、服务器端权限检查(排除权限问题)

SSH 对权限要求严格,权限过松会导致公钥被拒。正确的权限应为:

drwx------   .ssh/                     (700)
-rw-------   authorized_keys           (600)

修复命令:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R <用户>:<组> ~/.ssh

本次检查结果:目录与文件权限均正常(.ssh 为 700,authorized_keys 为 600,属主正确),权限不是本次故障原因。


五、私钥换行被破坏(本次问题原因之一)

私钥文件对格式非常敏感。在不同系统间复制、经复制粘贴或聊天/邮件工具传输时,常见以下破坏:

  • 换行符从 Unix 的 LF 变成 Windows 的 CRLF;
  • 多行被合并成一行,或换行丢失;
  • 开头/结尾的 -----BEGIN ... KEY----- / -----END ... KEY----- 被拆行或粘连;
  • 文件末尾缺少换行符。

诊断

cat -A <私钥文件> | head -5   # 行尾出现 ^M 即为 CRLF
file <私钥文件>               # 报告 "with CRLF line terminators" 即被污染

修复

dos2unix <私钥文件>
# 或
sed -i 's/\r$//' <私钥文件>
# 或
tr -d '\r' < <私钥文件> > <私钥文件>.fixed && mv <私钥文件>.fixed <私钥文件>

验证

ssh-keygen -y -f <私钥文件>
  • 能正常输出公钥 → 格式已修复;
  • 报错 invalid format / error in libcrypto → 内容在传输中缺字符,需重新用 scp/sftp 完整拷贝一份原始私钥。

建议:私钥不要用复制粘贴传输,改用 scp/sftp,并用 sha256sum 两端比对校验。


六、用 verbose 模式定位(排查核心手段)

ssh -i <私钥文件> -vvv <用户>@<主机>

日志里要盯住的几行

日志片段 含义
Trying private key: <私钥文件> 开始尝试这把私钥
sign_and_send_pubkey: ED25519 SHA256:... 私钥成功加载并签名,公钥已发给服务器
we sent a publickey packet, wait for reply 等待服务器判定
Server accepts key 服务器接受(成功)
Authentications that can continue: ... password 公钥被拒,回退到密码
Authentication failed. 认证失败

本次 verbose 结论

  • 私钥被成功加载并完成签名(是一把 ED25519 密钥),换行问题已修复,私钥格式正常;
  • 但服务器随后返回 Authentication failed,没有出现 Server accepts key;
  • 结论:该私钥对应的公钥没有登记在目标账号的 authorized_keys 里(本次为另一台主机、另一个账号,且私钥类型为 ED25519,与此前账号中的 RSA 密钥不同)。

七、最终解决方案:把正确的公钥装到目标服务器

# 本地:从私钥导出对应公钥
ssh-keygen -y -f <私钥文件> > <私钥文件>.pub

# 方式一:自动安装
ssh-copy-id -i <私钥文件>.pub <用户>@<主机>

# 方式二:手动追加(注意用 >> 不要覆盖),并修正权限
#   将 .pub 内容追加到服务器 ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

校验密钥是否匹配(通用方法)

# 本地私钥对应的公钥指纹
ssh-keygen -y -f <私钥文件> | ssh-keygen -lf -

# 服务器 authorized_keys 的指纹
ssh-keygen -lf ~/.ssh/authorized_keys

两边 SHA256:... 指纹一致 → 密钥匹配;不一致 → 本地私钥与服务器公钥不是一对。


八、排查结论小结

  1. 要求输入 passphrase 是加密私钥的正常现象,与公钥是否在 authorized_keys 无关;
  2. 第一台主机的失败,疑似私钥换行被破坏,dos2unix / 去 CRLF 后私钥恢复正常;
  3. 第二台主机换行问题已解决,私钥能正常签名,但失败原因是对应公钥未登记在目标账号的 authorized_keys 中;
  4. 服务器端 .ssh 与 authorized_keys 权限均正常,非权限问题;
  5. 最终解决:确认密钥匹配后,把正确的公钥安装到目标账号的 authorized_keys。

九、通俗版复述(大白话)

把 SSH 登录想象成”用钥匙开门进别人家”:

  • 你手里的私钥 = 一把钥匙。
  • 服务器上的 authorized_keys = 这家门锁里登记过的”允许进门的钥匙清单”。

你遇到的两个困惑,其实是两件完全不同的事:

第一件:为什么开门前先要我输一个密码(passphrase)?

因为你这把钥匙本身被装在一个”带密码的保险盒”里。你给钥匙加密的时候设了个密码,所以每次想用这把钥匙,得先输密码把保险盒打开,拿出钥匙。这个密码只是你自己家保险盒的密码,跟门锁那边登不登记过你完全没关系。门锁那边登记没登记,是另一码事。

所以”要输 passphrase”是正常的,不代表配置错了。嫌每次输麻烦,可以用 ssh-add 让电脑先帮你记一次,之后这段时间就不用反复输了。

第二件:为什么输完 passphrase,门还是不开,反而让我输”家门密码”?

这说明:保险盒打开了、钥匙也掏出来了、你也拿去捅门锁了 —— 但门锁一看”这把钥匙不在我的允许清单里”,于是拒绝了你,只好退而求其次问你:”那你知道家门密码吗?”

这里面有两种常见原因:

  1. 钥匙在运输中被弄坏了(私钥换行问题):你把钥匙从一台电脑复制到另一台时,格式被搞乱了(典型的是 Windows 和 Linux 换行符不一样),导致钥匙”缺了个齿”,根本捅不进锁。修法就是用 dos2unix 之类的命令把钥匙”掰正”,再用 ssh-keygen -y -f 确认钥匙能正常使用。

  2. 门锁根本没登记过这把钥匙(公钥不在 authorized_keys):第二台服务器就是这种情况。钥匙本身是好的、也成功捅锁了,但这家门锁的”允许清单”里压根没有你这把钥匙的记录,自然不让你进。解决办法就是:把你这把钥匙对应的”公钥”抄一份,登记到那台服务器的 authorized_keys 清单里(用 ssh-copy-id 一条命令就能搞定)。

最后一个小提醒:换电脑、换账号时,钥匙的”型号”也可能不一样(比如一台用的是 RSA,另一台用的是 ED25519)。要确认你现在用的这把钥匙,和目标服务器清单里登记的,确实是同一把。用 ssh-keygen -lf 比一下两边的”指纹”,一样就对,不一样就说明拿错钥匙或没登记。

一句话总结:输 passphrase 是开自己钥匙盒,正常;进不去是因为门锁没认你的钥匙——要么钥匙运输时坏了,要么钥匙没在门锁的清单里登记。

上一篇:
SSH 公钥认证:为什么用了私钥仍需输入密码
下一篇:
事件报告:Rancher 认证凭证失效导致模拟器测试全面失败
本文目录
本文目录