通用线程: OpenSSH 密钥管理,第 2 部分 介绍 ssh-agent 和
许多开发人员把优秀的 OpenSSH 用作古老的 telnet 和 rsh 命令的替代品,OpenSSH 不仅是安全的而且是加密的。OpenSSH 更加吸引人的特性之一是它能够使用基于一对互补的数字式“密钥”的 RSA 和 DSA 认证协议来认证用户。RSA 和 DSA 认证承诺 不必提供密码就能够同远程系统建立连接,这是其主要魅力之一。在第二篇文章里,Daniel 介绍<font face="Courier" size="2">ssh-agent</font>
(专用密钥高速缓存)及<font face="Courier" size="2">keychain</font>
,这个特殊的 bash 脚本的设计使基于密钥的认证极为方便和灵活。
介绍 ssh-agent
<font face="Courier" size="2">ssh-agent</font>
是专为既令人愉快又安全的处理 RSA 和 DSA 密钥而设计的特殊程序,它包括在 OpenSSH分发内(请参阅 本系列文章的第 1 部分以得到关于 RSA 和 DSA 认证的介绍)。不同于 <font face="Courier" size="2">ssh</font>
, <font face="Courier" size="2">ssh-agent</font>
是个长时间持续运行的守护进程(daemon),设计它的唯一目的就是对解密的专用密钥进行高速缓存。
<font face="Courier" size="2">ssh</font>
包含的内建支持允许它同 <font face="Courier" size="2">ssh-agent</font>
通信,允许 <font face="Courier" size="2">ssh</font>
不必每次新连接时都提示您要密码才能获取解密的专用密钥。对于 <font face="Courier" size="2">ssh-agent</font>
,您只要使用 <font face="Courier" size="2">ssh-add</font>
把专用密钥添加到 <font face="Courier" size="2">ssh-agent</font>
的高速缓存中。这是个一次性过程;用过 <font face="Courier" size="2">ssh-add</font>
之后, <font face="Courier" size="2">ssh</font>
将从 <font face="Courier" size="2">ssh-agent</font>
获取您的专用密钥,而不会提示要密码短语来烦您了。
使用 ssh-agent
让我们看一下整个 <font face="Courier" size="2">ssh-agent</font>
密钥高速缓存系统的工作过程。 <font face="Courier" size="2">ssh-agent</font>
启动时,在脱离 shell(外壳程序)并继续在后台运行之前它会输出一些重要的环境变量。以下是 <font face="Courier" size="2">ssh-agent</font>
开始时生成的输出的一些示例:
正如您所看到的,事实上 <font face="Courier" size="2">ssh-agent</font>
的输出是一系列 bash 命令;如果这些命令被执行,则将设置两个环境变量:SSH_AUTH_SOCK 和 SSH_AGENT_PID。内含的 export 命令使这些环境变量对之后运行的任何附加命令都可用。唔, 如果 shell 真对这些行进行计算,这一切才会发生,但是此时它们只是被打印到标准输出(stdout)而已。要使之确定,我们可以象下面这样调用 <font face="Courier" size="2">ssh-agent</font>
:
这个命令先让 bash 运行 <font face="Courier" size="2">ssh-agent</font>
后对 <font face="Courier" size="2">ssh-agent</font>
的输出进行计算。shell 以这种调用方式(使用反引号,而不是普通的单引号)设置并导出 SSH_AGENT_PID 及 SSH_AUTH_SOCK 变量,使这些变量对于您在登录会话期间启动的所有新进程都可用。
启动 <font face="Courier" size="2">ssh-agent</font>
的最佳方式就是把上面这行添加到您的 ~/.bash_profile 中;这样,在您的登录 shell 中启动的所有程序都将看到环境变量,而且能够定位 <font face="Courier" size="2">ssh-agent</font>
,并在需要的时候向其查询密钥。尤其重要的环境变量是 SSH_AUTH_SOCK;SSH_AUTH_SOCK 包含有 <font face="Courier" size="2">ssh</font>
和 <font face="Courier" size="2">scp</font>
可以用来同 <font face="Courier" size="2">ssh-agent</font>
建立对话的 UNIX 域套接字的路径。
使用 ssh-add
但是 <font face="Courier" size="2">ssh-agent</font>
启动时高速缓存当然是空的,里面不会有解密的专用密钥。在我们真能使用 <font face="Courier" size="2">ssh-agent</font>
之前,首先还需要使用 <font face="Courier" size="2">ssh-add</font>
命令把我们的专用密钥添加到 <font face="Courier" size="2">ssh-agent</font>
的高速缓存中。下面的示例中,我使用 <font face="Courier" size="2">ssh-add</font>
把我的 ~/.ssh/identity 专用 RSA 密钥添加到 <font face="Courier" size="2">ssh-agent</font>
的高速缓存中:
正如您所看到的, <font face="Courier" size="2">ssh-add</font>
要我的密码短语来对专用密钥进行解密并存储在 <font face="Courier" size="2">ssh-agent</font>
的高速缓存中以备使用。一旦您已经用 <font face="Courier" size="2">ssh-add</font>
把专用密钥(或多个密钥)添加到 <font face="Courier" size="2">ssh-agent</font>
的高速缓存中, 并在当前的 shell 中(如果您在 ~/.bash_profile 中启动 <font face="Courier" size="2">ssh-agent</font>
,情况应当是这样)定义 SSH_AUTH_SOCK,那么您可以使用 <font face="Courier" size="2">scp</font>
和 <font face="Courier" size="2">ssh</font>
同远程系统建立连接而不必提供密码短语。
ssh-agent 的不足之处
<font face="Courier" size="2">ssh-agent</font>
确实棒,但是其缺省配置还是会留给我们一些小小的不便。让我们来看一下这些不足吧。
首先,~/.bash_profile 中的 <font face="Courier" size="2">eval `ssh-agent`</font>
使每次登录会话都会启动一个新的 <font face="Courier" size="2">ssh-agent</font>
副本;这不仅仅是有一丁点儿浪费,而且还意味着您得使用 <font face="Courier" size="2">ssh-add</font>
向每个新的 <font face="Courier" size="2">ssh-agent</font>
副本添加专用密钥。如果您只想打开系统上的一个终端或控制台,这没什么大不了的,但是我们中大多数人打开相当多的终端,每次新打开控制台都需要键入密码短语。从技术角度讲,既然一个 <font face="Courier" size="2">ssh-agent</font>
进程的确应当足够了,要是我们还需这样做,这毫无道理。
有关 <font face="Courier" size="2">ssh-agent</font>
的缺省设置的另外一个问题是它同 cron 作业不兼容。由于 cron 作业是 cron 进程启动的,这些作业无法从它们的环境中继承 SSH_AUTH_SOCK 变量,因而也无从知道 <font face="Courier" size="2">ssh-agent</font>
进程正在运行以及如何同它联系。事实证明这个问题也是可以修补的。