SSH 公钥认证:为什么用了私钥仍需输入密码
背景场景
- 客户端主机(下称 Client)已能通过 SSH 登录到服务端主机(下称 Server)。
- Client 的公钥已写入 Server 的
~/.ssh/authorized_keys,因此 Client 可以免密登录 Server。 - 相关权限设置正确:
.ssh目录为700,authorized_keys为600。 - 随后,将 Server 自身的私钥
id_rsa复制到 Client 上(重命名保存,权限600)。 - 使用
ssh -i <复制来的私钥> user@Server登录时,仍然需要输入密码,无法免密。
问题现象
ssh -i id_rsa.copy user@Server # 仍然提示输入密码
根本原因
SSH 公钥认证的核心规则是一对密钥必须匹配:
客户端使用的私钥 ←→ 服务端 authorized_keys 中的公钥
(两者必须是同一密钥对)
在这个场景中:
- 能免密的那次,用的是 Client 的私钥,而 Server 的
authorized_keys里放的正是 Client 的公钥,两者配对成功。 - 复制过来的是 Server 的私钥,它对应的是 Server 自己的公钥。
- 但 Server 的
authorized_keys中并没有加入 Server 自己的公钥,因此服务端找不到与该私钥匹配的公钥,认证失败,退回到密码登录。
关键点:拥有某个私钥,并不等于拥有登录权限。能否免密,取决于该私钥对应的公钥是否存在于目标服务器的
authorized_keys中。
解决方法
如果希望用 Server 的私钥登录 Server,需要把 Server 自己的公钥也加入其 authorized_keys:
# 在 Server 上执行
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
完成后,用 Server 的私钥即可免密登录:
ssh -i id_rsa.copy user@Server
认证匹配关系对照表
| 客户端使用的私钥 | 服务端 authorized_keys 中的公钥 | 结果 |
|---|---|---|
| Client 的私钥 | Client 的公钥 | 免密成功 |
| Server 的私钥 | 仅有 Client 的公钥 | 失败,需密码 |
| Server 的私钥 | 已加入 Server 的公钥 | 免密成功 |
权限要求(补充)
公钥认证对权限敏感,以下设置为必要条件:
| 路径 | 推荐权限 |
|---|---|
~/.ssh 目录 |
700 |
~/.ssh/authorized_keys |
600 |
| 私钥文件 | 600 |
权限过宽(如组或其他用户可读写)会导致 SSH 出于安全考虑拒绝使用相关密钥。
通俗版复述
你可以把 SSH 免密登录想象成「锁和钥匙」的关系,但方向很容易搞反。
- 公钥好比一把挂在门上的「锁」。
- 私钥好比你手里的「钥匙」。
- 想开门,你手里的钥匙必须能对上门上的那把锁——它们得是配套的一对。
第一次能免密登录,是因为:你把自己这把锁挂到了对方的门上(公钥放进了对方的 authorized_keys),而你手里拿的正是能开这把锁的钥匙(自己的私钥)。钥匙和锁配套,门自然就开了。
后来你把对方的钥匙(对方的私钥)复制到自己这边,想用它来开门。可问题是,对方门上挂的还是你的那把锁,并没有挂对方自己的锁。于是你拿着对方的钥匙,却找不到对应的锁可以开,门打不开,只能退回去用密码。
所以要记住一句话:光有钥匙没用,必须门上挂着这把钥匙能开的那把锁。
如果真想用对方的钥匙开对方的门,就得先把对方自己的那把锁也挂到门上(把对方的公钥加进 authorized_keys)。锁和钥匙配齐了,才能免密进门。