使用公钥-私钥对的无密码 SSH
如果您经常使用 SSH 命令和远程主机,您可能会发现使用密钥对代替密码会很方便。远程系统无需在每次连接时都提示输入密码,而是可以使用公钥和私钥对自动协商身份验证。
私钥安全地保存在您自己的工作站上,而公钥则存放在您访问的每个远程系统上的特定位置。您的私钥可能在本地使用密码保护。本地缓存程序(例如ssh-agent
或 )gnome-keyring
允许您定期输入该密码,而不是每次使用密钥访问远程系统时都输入。
[ 免费下载:高级 Linux 命令备忘单。]
生成密钥对并传播公钥
生成密钥对并传播公钥其实比听起来简单得多。让我们来详细了解一下。
生成密钥
生成密钥对的最少工作包括运行命令ssh-keygen
并在所有提示符下选择默认值:
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/training/.ssh/id_rsa):
Created directory '/home/training/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/training/.ssh/id_rsa.
Your public key has been saved in /home/training/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:qOoqJFfbfnBFMZ6WFsZQZfy6WXTfcknQEd0B+quTjHw training@example.com
The key's randomart image is:
+---[RSA 2048]----+
| .+*+o.o+*|
| oo*o. .o|
| .*. .. |
| . . o. . o..|
| . o. S. +..+|
|... ..o . . +.+|
|o. .. o. o .= o |
|. . . .o E+ |
|ooo . ... |
+----[SHA256]-----+
存储密钥的默认位置在~/.ssh
目录中,如果不存在则会创建该目录:
$ ls -al .ssh
total 16
drwx------. 2 training training 4096 Aug 12 07:43 .
drwx------. 5 training training 4096 Aug 12 07:43 ..
-rw-------. 1 training training 1843 Aug 12 07:43 id_rsa
-rw-r--r--. 1 training training 415 Aug 12 07:43 id_rsa.pub
允许此命令创建目录还可确保所有者和权限设置正确。如果私钥的权限太开放,某些应用程序将不会使用密钥。
以 结尾的文件.pub
是需要传输到远程系统的公钥。该文件包含一行:协议、密钥和用作标识符的电子邮件。该ssh-keygen
命令的选项允许您指定不同的标识符:
$ cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZ4SCcMX1EK31G/qLyCs3PaFcWkx0QA61OwQNHYztvrg7iD/etN4S5UP6ugHjTcUvqD/fZJFBJeryK0Hz0FzejKYiJBxQuUqadyXFSW30VnW6mAzgNoz20rGc2mipUrsaqdBWWv5U7vX8sgjEHEgVHzq6pfWj681PtikJ8Dss1IvPiPvOoRz2jb1dQnnrAVqMDGeWbm4yjYQamPvnLo1Hy23NgXpZ7KXv9PuDDu3tqcoMUqFk7sHswMrCCUY9SWOD5JBbhD3JX4LPs68WWbETOqOQ3a9ebTsL3wRPSbuu/djhL9Qmd8fN2OaM2U2zFpeE3NzBq4KT/ml6RTv44EMuh training@example.com
生成密钥对后,该ssh-keygen
命令还会显示此密钥独有的指纹和随机图像。此信息可以与可能需要验证您的公钥的其他人共享。
稍后您可以使用以下方式查看这些内容:
$ ssh-keygen -lv
Enter file in which the key is (/home/training/.ssh/id_rsa):
该-l
选项列出了指纹,该-v
选项添加了 ASCII 艺术。
将公钥传播到远程系统
如果当前已启用密码验证,则将公钥传输到远程主机的最简单方法是使用以下命令ssh-copy-id
。如果您使用密钥的默认名称,则只需指定远程用户和主机:
$ ssh-copy-id susan@streamer
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/training/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
susan@streamer's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'susan@streamer'"
and check to make sure that only the key(s) you wanted were added.
按照输出中的说明,验证您是否可以使用密钥对进行连接。如果您实施了密码,系统将提示您输入密码以使用私钥:
$ ssh susan@streamer
Last login: Sat Aug 10 14:09:33 2019 from X.X.X.X
检查生成的授权密钥文件。这是附加公钥的地方。如果目录或文件不存在,则它(或它们)是使用正确的所有权和权限创建的。每行都是一个授权公钥:
[susan@streamer ~]$ cat .ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZ4SCcMX1EK31G/qLyCs3PaFcWkx0QA61OwQNHYztvrg7iD/etN4S5UP6ugHjTcUvqD/fZJFBJeryK0Hz0FzejKYiJBxQuUqadyXFSW30VnW6mAzgNoz20rGc2mipUrsaqdBWWv5U7vX8sgjEHEgVHzq6pfWj681PtikJ8Dss1IvPiPvOoRz2jb1dQnnrAVqMDGeWbm4yjYQamPvnLo1Hy23NgXpZ7KXv9PuDDu3tqcoMUqFk7sHswMrCCUY9SWOD5JBbhD3JX4LPs68WWbETOqOQ3a9ebTsL3wRPSbuu/djhL9Qmd8fN2OaM2U2zFpeE3NzBq4KT/ml6RTv44EMuh training@example.com
要撤销此密钥对的访问权限,请删除公钥行。
授权密钥文件中的此行中可以添加许多其他选项来控制访问。这些选项通常由管理员使用,用于将公钥放置在有限制的系统上。这些限制可能包括连接可能来自何处、可能运行哪些命令,甚至指示何时停止接受此密钥的日期。手册页中列出了这些选项和更多选项sshd
。
更改密码
如果您需要更改私钥上的密码,或者您最初设置了一个空密码并希望稍后获得该保护,请使用ssh-keygen
带有以下-p
选项的命令:
$ ssh-keygen -p
Enter file in which the key is (/home/training/.ssh/id_rsa):
Key has comment 'training@example.com'
Enter new passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved with the new passphrase.
您可以添加其他选项以在命令行上指定密钥 ( -f
) 以及旧 ( -P
) 或新 ( -N
) 密码。请记住,在命令行上指定的任何密码都将保存在您的 shell 历史记录中。
请参阅ssh-keygen
手册页以了解更多选项。
旋转密钥
虽然公钥本身是用来共享的,但请记住,如果有人获得了您的私钥,他们就可以使用它来访问所有拥有公钥的系统。这些密钥对也没有像GNU Privacy Guard (GPG) 密钥或公钥基础设施 (PKI) 证书那样的有效期。
如果您有任何理由怀疑私钥已被盗用或以其他方式泄露,则应更换该密钥对。必须从所有系统中删除旧公钥,使用 生成新密钥ssh-keygen
,并将新公钥传输到所需的远程系统。
如果您出于预防措施而轮换密钥并且不担心泄露,则可以在删除旧密钥之前使用旧密钥对来验证新公钥的传输。
使用空密码是一个好主意吗?
在考虑为 SSH 私钥设置空密码时,有几件事需要考虑。
私钥文件有多安全?
如果您倾向于使用多个客户端系统工作,并且想要拥有密钥的多个副本或在可移动媒体上保留一份副本,那么在私钥上设置密码确实是一个好主意。此做法是对使用加密媒体保护密钥文件访问的补充。
然而,如果您只有一份私钥副本,并且将其保存在一个安全且未共享的系统中,那么为了以防万一,使用密码只是多一层的保护。
请记住,更改一个副本上的密码不会更改其他副本上的密码。密码只是锁定对特定密钥文件的访问。
您为什么认为需要一个空密码?
密钥有空密码的情况。一些需要在系统之间自动传输文件的实用程序需要无密码方法进行身份验证。该kdump
实用程序配置为使用 SSH 将内核转储到远程系统就是一个例子。
另一个常见用途是为旨在无人值守运行的脚本(例如来自 cron 作业)生成密钥对。
那么中间立场的替代方案怎么样?
受密码保护的私钥本身要求每次使用密钥时都输入密码。这种设置感觉不像无密码 SSH。但是,有缓存机制允许您输入密钥密码一次,然后反复使用密钥而无需重新输入该密码。
OpenSSH 附带一个ssh-agent
守护进程和一个ssh-add
用于缓存解锁私钥的实用程序。GNOME 桌面还有一个密钥环守护进程,用于存储密码和机密,还实现了 SSH 代理。
缓存密钥的有效期可由每个代理配置,也可在添加密钥时配置。在许多情况下,默认的有效期为无限,但用户退出系统时会清除缓存。每次登录会话时,系统只会提示您输入一次密码。
如果有一个预定的应用程序需要在用户登录会话之外运行,则可以使用密钥或其他密码管理器来自动解锁密钥。例如,Ansible Tower将凭据存储在安全数据库中。该数据库包含用于连接远程系统(托管节点)的 SSH 私钥,以及这些私钥所需的任何密码。存储这些凭据后,可以安排一项作业定期运行剧本。
自动传播
集中式身份管理器(例如FreeIPA)可以协助密钥传播。将公钥作为用户帐户的属性上传到服务器,然后根据需要将其传播到域中的主机。FreeIPA 还可以为密钥的使用位置提供额外的基于主机的访问控制。
密钥也可以使用 Ansible 模块进行分发。该openssh_keypair
模块用于ssh-keygen
生成密钥,并authorized_key
为特定用户帐户添加和删除 SSH 授权密钥。
总结
SSH 密钥对只是实现无需密码的自动化身份验证的一种方式。在集中用户管理的网络上,尝试减少密码的使用时,使用通用安全服务应用程序编程接口 (GSSAPI) 身份验证也很常见。当单点登录 (SSO) 尚不可用时,SSH 密钥对是更易于实现的选项。
许多源代码存储库使用 SSH 密钥授予访问权限。您可以将公钥上传到托管组织(例如 Fedora 帐户系统、GitLab 或 GitHub 网站)中的帐户,并在将内容拉取和推送到存储库时使用该密钥对进行身份验证。