OpenSSH 密钥管理:ssh-agent和keychain

本文介绍如何使用ssh-agent与keychain管理SSH密钥,避免频繁输入密码短语的不便,通过一次性添加密钥到ssh-agent的高速缓存中,实现无缝连接远程系统。

介绍 ssh-agent

  ssh-agent 是专为既令人愉快又安全的处理 RSA 和 DSA 密钥而设计的特殊程序,它包括在OpenSSH分发内(请参阅 本系列文章的第 1 部分以得到关于 RSA 和 DSA 认证的介绍)。不同于 ssh , ssh-agent 是个长时间持续运行的守护进程(daemon),设计它的唯一目的就是对解密的专用密钥进行高速缓存。

  ssh 包含的内建支持允许它同 ssh-agent 通信,允许 ssh 不必每次新连接时都提示您要密码才能获取解密的专用密钥。对于 ssh-agent ,您只要使用 ssh-add 把专用密钥添加到 ssh-agent 的高速缓存中。这是个一次性过程;用过 ssh-add 之后, ssh 将从 ssh-agent 获取您的专用密钥,而不会提示要密码短语来烦您了。

  使用 ssh-agent

  让我们看一下整个 ssh-agent 密钥高速缓存系统的工作过程。 ssh-agent 启动时,在脱离 shell(外壳程序)并继续在后台运行之前它会输出一些重要的环境变量。以下是 ssh-agent 开始时生成的输出的一些示例:

 

双击代码全选
1
2
3
4
% ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-XX4LkMJS/agent.26916; export SSH_AUTH_SOCK;
SSH_AGENT_PID=26917; export SSH_AGENT_PID;
echo Agent pid 26917;

  正如您所看到的,事实上 ssh-agent 的输出是一系列 bash 命令;如果这些命令被执行,则将设置两个环境变量:SSH_AUTH_SOCK 和 SSH_AGENT_PID。内含的 export 命令使这些环境变量对之后运行的任何附加命令都可用。唔, 如果 shell 真对这些行进行计算,这一切才会发生,但是此时它们只是被打印到标准输出(stdout)而已。要使之确定,我们可以象下面这样调用 ssh-agent :

 

双击代码全选
1
eval `ssh-agent`

  这个命令先让 bash 运行 ssh-agent 后对 ssh-agent 的输出进行计算。shell 以这种调用方式(使用反引号,而不是普通的单引号)设置并导出 SSH_AGENT_PID 及 SSH_AUTH_SOCK 变量,使这些变量对于您在登录会话期间启动的所有新进程都可用。

  启动 ssh-agent 的最佳方式就是把上面这行添加到您的 ~/.bash_profile 中;这样,在您的登录 shell 中启动的所有程序都将看到环境变量,而且能够定位 ssh-agent ,并在需要的时候向其查询密钥。尤其重要的环境变量是 SSH_AUTH_SOCK;SSH_AUTH_SOCK 包含有 ssh 和 scp 可以用来同 ssh-agent 建立对话的 UNIX 域套接字的路径。

  使用 ssh-add

  但是 ssh-agent 启动时高速缓存当然是空的,里面不会有解密的专用密钥。在我们真能使用 ssh-agent 之前,首先还需要使用 ssh-add 命令把我们的专用密钥添加到 ssh-agent 的高速缓存中。下面的示例中,我使用 ssh-add 把我的 ~/.ssh/identity 专用 RSA 密钥添加到 ssh-agent 的高速缓存中:

 

双击代码全选
1
2
3
4
# ssh-add ~/.ssh/identity
Need passphrase for /home/drobbins/.ssh/identity
Enter passphrase for /home/drobbins/.ssh/identity
(enter passphrase)

  正如您所看到的, ssh-add 要我的密码短语来对专用密钥进行解密并存储在 ssh-agent 的高速缓存中以备使用。一旦您已经用 ssh-add 把专用密钥(或多个密钥)添加到 ssh-agent 的高速缓存中, 并在当前的 shell 中(如果您在 ~/.bash_profile 中启动 ssh-agent ,情况应当是这样)定义 SSH_AUTH_SOCK,那么您可以使用 scp 和 ssh 同远程系统建立连接而不必提供密码短语。

  ssh-agent 的不足之处

  ssh-agent 确实棒,但是其缺省配置还是会留给我们一些小小的不便。让我们来看一下这些不足吧。

  首先,~/.bash_profile 中的 eval `ssh-agent` 使每次登录会话都会启动一个新的 ssh-agent 副本;这不仅仅是有一丁点儿浪费,而且还意味着您得使用 ssh-add 向每个新的 ssh-agent 副本添加专用密钥。如果您只想打开系统上的一个终端或控制台,这没什么大不了的,但是我们中大多数人打开相当多的终端,每次新打开控制台都需要键入密码短语。从技术角度讲,既然一个 ssh-agent 进程的确应当足够了,要是我们还需这样做,这毫无道理。

  有关 ssh-agent 的缺省设置的另外一个问题是它同 cron 作业不兼容。由于 cron 作业是 cron 进程启动的,这些作业无法从它们的环境中继承 SSH_AUTH_SOCK 变量,因而也无从知道 ssh-agent 进程正在运行以及如何同它联系。事实证明这个问题也是可以修补的。

  开始用到 keychain

  为了解决这些问题,我编写了一个有用的 ssh-agent 前端,它基于 bash,叫做 keychain 。 keychain 的特别之处在于它允许 每个系统使用一个 ssh-agent 进程,而非每次登录会话。这意味着您只需对每个专用密钥执行一次 ssh-add ,就一次。正如我们稍后将要看到的一样, keychain 甚至有助于优化 ssh-add ,而这只要它试图向那些正在运行的 ssh-agent 添加其高速缓存中没有的专用密钥。

GJCKGD09064:~ 10280281$ ssh -Tv git@gitlab.com OpenSSH_9.9p1, LibreSSL 3.3.6 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Reading configuration data /etc/ssh/ssh_config.d/100-macos.conf debug1: /etc/ssh/ssh_config.d/100-macos.conf line 1: Applying options for * debug1: Reading configuration data /etc/ssh/crypto.conf debug1: Authenticator provider $SSH_SK_PROVIDER did not resolve; disabling debug1: Connecting to gitlab.com port 22. debug1: Connection established. debug1: identity file /Users/10280281/.ssh/id_rsa type -1 debug1: identity file /Users/10280281/.ssh/id_rsa-cert type -1 debug1: identity file /Users/10280281/.ssh/id_ecdsa type -1 debug1: identity file /Users/10280281/.ssh/id_ecdsa-cert type -1 debug1: identity file /Users/10280281/.ssh/id_ecdsa_sk type -1 debug1: identity file /Users/10280281/.ssh/id_ecdsa_sk-cert type -1 debug1: identity file /Users/10280281/.ssh/id_ed25519 type 3 debug1: identity file /Users/10280281/.ssh/id_ed25519-cert type -1 debug1: identity file /Users/10280281/.ssh/id_ed25519_sk type -1 debug1: identity file /Users/10280281/.ssh/id_ed25519_sk-cert type -1 debug1: identity file /Users/10280281/.ssh/id_xmss type -1 debug1: identity file /Users/10280281/.ssh/id_xmss-cert type -1 debug1: identity file /Users/10280281/.ssh/id_dsa type -1 debug1: identity file /Users/10280281/.ssh/id_dsa-cert type -1 debug1: Local version string SSH-2.0-OpenSSH_9.9 debug1: Remote protocol version 2.0, remote software version GitLab-SSHD debug1: compat_banner: no match: GitLab-SSHD debug1: Authenticating to gitlab.com:22 as 'git' debug1: load_hostkeys: fopen /Users/10280281/.ssh/known_hosts2: No such file or directory debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts2: No such file or directory debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: algorithm: ecdh-sha2-nistp256 debug1: kex: host key algorithm: ssh-ed25519 debug1: kex: server->client cipher: aes128-gcm@openssh.com MAC: <implicit> compression: none debug1: kex: client->server cipher: aes128-gcm@openssh.com MAC: <implicit> compression: none debug1: expecting SSH2_MSG_KEX_ECDH_REPLY debug1: SSH2_MSG_KEX_ECDH_REPLY received debug1: Server host key: ssh-ed25519 SHA256:eUXGGm1YGsMAS7vkcx6JOJdOGHPem5gQp4taiCfCLB8 debug1: load_hostkeys: fopen /Users/10280281/.ssh/known_hosts2: No such file or directory debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts2: No such file or directory debug1: Host 'gitlab.com' is known and matches the ED25519 host key. debug1: Found key in /Users/10280281/.ssh/known_hosts:2 debug1: ssh_packet_send2_wrapped: resetting send seqnr 3 debug1: rekey out after 4294967296 blocks debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: ssh_packet_read_poll2: resetting read seqnr 3 debug1: SSH2_MSG_NEWKEYS received debug1: rekey in after 4294967296 blocks debug1: SSH2_MSG_EXT_INFO received debug1: kex_ext_info_client_parse: server-sig-algs=<ssh-ed25519,sk-ssh-ed25519@openssh.com,sk-ecdsa-sha2-nistp256@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,rsa-sha2-256,rsa-sha2-512,ssh-rsa,ssh-dss> debug1: kex_ext_info_check_ver: ping@openssh.com=<0> debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey debug1: Next authentication method: publickey debug1: get_agent_identities: bound agent to hostkey debug1: get_agent_identities: agent returned 1 keys debug1: Will attempt key: /Users/10280281/.ssh/id_ed25519 ED25519 SHA256:SuAWMQGFny0Fbbb0v4XrQfli2ahKRO7GFDPQ+kRiSUU agent debug1: Will attempt key: /Users/10280281/.ssh/id_rsa debug1: Will attempt key: /Users/10280281/.ssh/id_ecdsa debug1: Will attempt key: /Users/10280281/.ssh/id_ecdsa_sk debug1: Will attempt key: /Users/10280281/.ssh/id_ed25519_sk debug1: Will attempt key: /Users/10280281/.ssh/id_xmss debug1: Will attempt key: /Users/10280281/.ssh/id_dsa debug1: Offering public key: /Users/10280281/.ssh/id_ed25519 ED25519 SHA256:SuAWMQGFny0Fbbb0v4XrQfli2ahKRO7GFDPQ+kRiSUU agent debug1: Authentications that can continue: publickey debug1: Trying private key: /Users/10280281/.ssh/id_rsa debug1: Trying private key: /Users/10280281/.ssh/id_ecdsa debug1: Trying private key: /Users/10280281/.ssh/id_ecdsa_sk debug1: Trying private key: /Users/10280281/.ssh/id_ed25519_sk debug1: Trying private key: /Users/10280281/.ssh/id_xmss debug1: Trying private key: /Users/10280281/.ssh/id_dsa debug1: No more authentication methods to try. git@gitlab.com: Permission denied (publickey).
最新发布
08-14
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值