科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网安全频道OpenSSH 密钥管理:ssh-agent和keychain

OpenSSH 密钥管理:ssh-agent和keychain

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

对于不频繁访问又需要偶而执行安全拷贝任务的服务器而言,比如,备份服务器、防火墙及路由器, --clear选项是一个理想的选择。

作者:Daniel Robbins 来源:IBM 2008年6月12日

关键字: ssh OpenSSH

  • 评论
  • 分享微博
  • 分享邮件

  介绍 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开始时生成的输出的一些示例:

  % 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:

  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的高速缓存中:

  # 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添加其高速缓存中没有的专用密钥。

  以下对 keychain如何工作从头到尾浏览一遍。从 ~/.bash_profile 中启动时, keychain将首先查看 ssh-agent是否已经在运行了。如果没有,它就启动 ssh-agent并把重要的 SSH_AUTH_SOCK 和 SSH_AGENT_PID 变量记录在 ~/.ssh-agent 文件中,一方面为了安全而保存,另一方面也是为了以后的使用。这是启动 keychain的最佳途径;同使用平淡无奇的老式 ssh-agent一样,我们在 ~/.bash_profile 内部执行必要的配置:

  #!/bin/bash

  #example ~/.bash_profile file

  /usr/bin/keychain ~/.ssh/id_rsa

  #redirect ~/.ssh-agent output to /dev/null to zap the annoying

  #"Agent PID" message

  source ~/.ssh-agent >/dev/null

  正如您所看到的,对于 keychain我们用 source 命令读入并执行 ~/.ssh-agent 文件,而不是象我们直接使用 ssh-agent时所做的对输出进行计算。但是,结果是一样的:定义了非常重要的 SSH_AUTH_SOCK,而且正运行 ssh-agent以备使用。同时,因为 SSH_AUTH_SOCK 被记录在 ~/.ssh-agent 里,只要用 source 命令读入并执行 ~/.ssh-agent 文件,就可以轻易的把我们的 shell 脚本及 cron 作业同 ssh-agent连接起来。 keychain本身也利用了这个文件;您应该记住 keychain启动时,它会查看现有的 ssh-agent是否正在运行。如果是,则它使用 ~/.ssh-agent 文件来获得适当的 SSH_AUTH_SOCK 设置,这样就使 keychain能使用现有的代理程序而不必新启动一个。只有在 ~/.ssh-agent 文件无效(指向一个不存在的 ssh-agent)或 ~/.ssh-agent 文件本身不存在时, keychain才会启动新的 ssh-agent进程。

  安装 keychain

  安装 keychain很容易。首先,直接到 keychain 工程主页下载可用的 keychain源压缩文档的最新版本。然后,安装如下:

  # tar xzvf keychain-1.0.tar.gz

  # cd keychain-1.0

  # install -m0755 keychain /usr/bin

  既然 keychain在 /usr/bin/ 目录下,就请把它添加到您的 ~/.bash_profile 中,并把您的专用密钥路径作为参数。下面是一个既标准又好的启用 keychain的 ~/.bash_profile:

  启用 keychain 的 ~/.bash_profile 示例

  #!/bin/bash

  #on this next line, we start keychain and point it to the private keys that

  #we'd like it to cache

  /usr/bin/keychain ~/.ssh/id_rsa ~/.ssh/id_dsa

  source ~/.ssh-agent >/dev/null

  #sourcing ~/.bashrc is a good thing

  source ~/.bashrc

  Keychain 生效

  您一为每次登录时调用 keychain配置好了 ~/.bash_profile,就请先退出再登录回来。在您再次登录时, keychain将启动 ssh-agent,并记录下 ~/.ssh-agent 中的代理程序环境变量设置,然后提示您输入在 ~/.bash_profile 中的 keychain命令行指定的所有专用密钥的密码短语:

  Keychain 首次启动

  您一输入密码短语,您的专用密钥就会被高速缓存,同时 keychain将退出。接着,用 source 命令读入并执行 ~/.ssh-agent,初始化您的登录会话以便同 ssh-agent一起使用。现在,如果您退出,然后再登录回来,将发现 keychain会找到现有的 ssh-agent进程;在您退出时,它并没有终止。此外, keychain将验证您指定的专用密钥是否已经在 ssh-agent的高速缓存中了。如果没有,那么将会提示您输入正确的密码短语,但如果一切进展顺利,则现有 ssh-agent仍包含有您以前添加的专用密钥;这意味着不会提示您输入密码:

  Keychain 找到现有的 ssh-agent

  祝贺您!您刚才已经登录了,应该能够用 ssh和 scp连到远程系统;您不必一登录就使用 ssh-add,而且 ssh和 scp也不会提示您输入密码短语。事实上,只要初始的 ssh-agent进程一直在运行,您就能不提供密码登录并建立 ssh连接。 ssh-agent进程持续运行直到机器重新启动也是很有可能的;由于您最可能在 Linux系统上这样设置,所以也许一连几个月您都不必输入密码短语!欢迎来到安全的、使用 RSA 和 DSA 认证无密码连接的世界。

  继续创建几个新的登录会话,您会发现每次 keychain都会准确无误的“钩住”到同一 ssh-agent进程。不要忘记您也可以使 cron 作业和脚本“钩住”正在运行的 ssh-agent进程。要在 shell 脚本和 cron 作业中使用 ssh或 scp命令,只要确保先用 source 命令读入并执行 ~/.ssh-agent:

  source ~/.ssh-agent

  然后,随后所有的 ssh或 scp命令就能够找到当前正在运行的 ssh-agent,并且象您在 shell 中一样能建立安全的无密码连接。

  Keychain 选项

  您启动并运行 keychain后,一定要键入 keychain --help以熟悉 keychain所有的命令行选项。我们要特别看一下这个选项: -clear选项。

  还记得我在第 1 部分里阐释了使用不加密专用密钥是一种危险的做法,因为这种做法允许其它人盗用您的专用密钥不提供密码就可以从所有系统登录到您的远程帐户。唔,尽管 keychain不易遭到这种滥用(只要您使用加密的专用密钥就行),但仍存在有可能可以利用的弱点,同 keychain使得“钩住”长时间持续运行的 ssh-agent进程如此容易这一事实直接相关。我想,如果闯入者以某种方式能想出我的密码或密码短语,还能登录进入我的本地系统,会发生什么事情呢?如果出于某种原因他们能以我的用户名登录,那么 keychain就会立刻授权他们访问我的解密的专用密钥,使他们可以轻而易举的访问我的其它帐户。

  现在,在继续下面的内容之前,让我们先客观的表述一下安全威胁。如果由于某种原因一些恶意的用户能以我的身份登录, keychain确实会允许他们访问我的远程帐户。但,尽管如此,这位闯入者要偷到我的加密的专用密钥非常困难,因为它们仍旧在磁盘上保持着加密状态。而且,得到我的专用密钥访问权要求用户真的以我的身份 登录,不单单是阅读我的目录中的文件而已。因此,滥用 ssh-agent是比只偷到一个不加密的专用密钥困难得多的一项任务,后者只需要闯入者通过某种手段获得我在 ~/.ssh 里的文件的访问权,而不管是否是以我的身份登录。不过,如果闯入者能够成功的以我的身份登录,通过使用我的加密专用密钥他们造成相当多的额外损害。所以,如果您刚好在您不频繁登录或没有对安全缺口进行密切监视的一台服务器上使用 keychain,那么请您考虑使用 --clear选项以提供附加的安全层。

  --clear选项允许您让 keychain假定把每次以您的帐户的新登录都当作是可能的安全缺口,直到能证明并非如此。当您启动 keychain时使用了 --clear选项时,您登录的时候 keychain会立即刷新 ssh-agent的高速缓存里的所有专用密钥,此后才执行它的常规职责。这样,如果您是一位闯入者,则 keychain会提示您输入密码短语而不会让您访问现有的高速缓存中的密钥集合。但是,虽然这样增强了安全性,却使情况有点更不方便,尤其好象完全是 ssh-agent在运行,而 keychain并没有运行。此处,情况常常是这样,一个人可以选择或者安全性更高,或更方便,但不能两者兼得。

  尽管如此,使用带有 --clear的 keychain仍然比只用 ssh-agent要好;请记住,当您使用 keychain --clear时,您的 cron 作业和脚本仍然能建立无密码连接;这是因为专用密钥是在 登录时刷新,而不是在 退出时。由于从系统退出不会构成潜在的安全缺口,因而没有理由要 keychain来刷新 ssh-agent的密钥作为响应。因此,对于不频繁访问又需要偶而执行安全拷贝任务的服务器而言,比如,备份服务器、防火墙及路由器, --clear选项是一个理想的选择。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章