当我为用户加载了私钥时,我可以运行ssh-copy-id user@remotehostname
并提示输入密码。当我输入正确的密码后,我现在可以使用密钥登录了。我以前总是将此命令-i <path to public key>
作为参数运行,但现在意识到我不需要公钥的路径。
当我以 user@hostname 身份登录时,我会搜索 .ssh/authorized_keys 文件,并查看与我的私钥匹配的公钥,这让我感到困惑——我从未提供过公钥。
当我运行命令时,ssh-copy-id 如何知道哪个公钥与我在本地加载的私钥匹配?当我不提供授权密钥文件时,它怎么知道要添加什么?
我希望我很清楚——我一直在跑步ssh-copy-id -i <public key>
,这对我来说很有意义——它登录并将公钥复制到授权的密钥文件中。但是如果我不提供公钥(即我ssh-add <private key>
在运行 ssh-copy-id 之前运行),只要我加载了私钥,它仍然可以工作,而且我不明白它是如何获取公钥的。
编辑:澄清一下,我没有保留默认的 id*.pub 命名约定。因此,我在手册页中看到的关于搜索 id*.pub 的逻辑似乎并不适用。事实上,我可以创建一个名为 randompair 的密钥对,加载 randompair,将 rendompair.pub 重命名为 newname.pub,运行 ssh-copy-id,它仍然会加载正确的公钥。
查看 bash 脚本本身让我对它是如何实现这一点感到有些困惑。
这在最近系统的手册页中有很好的记录。请注意,脚本有几个不同的版本;Arch Linux和RHEL/CentOS似乎与Debian/Ubuntu具有相同的版本,但FreeBSD的选项略有不同。
默认情况下,
ssh-copy-id
调用ssh-add -L
列出您在 SSH 代理中注册的密钥。ssh-add -L
输出您在代理中拥有私钥的公钥列表。您可能想知道代理如何做到这一点,因为您也没有向它传递公钥。答案是始终可以从私钥重建公钥(对于 SSH 支持的所有密码系统都是如此,但大多数不支持)。然而,这仅适用于密钥的“数学”部分。公钥文件还可以包含一个注释(可以用 设置ssh-keygen -C
),代理不会加载这个注释,所以如果你使用ssh-copy-id
它并且它通过代理获取一个密钥,远程主机不会有这个注释authorized_keys
。如果没有正在运行的代理或没有任何密钥,则最近的 Linux
ssh-copy-id
查找(直接来自手册页)旧版本的脚本和非 Linux 版本没有这种最近的文件行为。据我记得,即使是旧版本也没有探测代理,默认情况下只是读取默认路径
~/.ssh/id_rsa.pub
。ssh-copy-id 使用 [1] ssh-add -L 命令,它允许 [2]
所以,如果没有 -i 提供,它可以通过这种方式找到它。
[1] https://linux.die.net/man/1/ssh-copy-id
[2]如何检查哪些 SSH 密钥当前处于“活动状态”?