OpenSSH 密钥管理,第 3 部分
2007-07-09 10:42
288 查看
通用线程: OpenSSH 密钥管理,第 3 部分代理程序转发和 keychain 改进 |
级别: 初级 Daniel Robbins, 总裁兼首席执行官, Gentoo Technologies,Inc. 2002 年 2 月 01 日 在这一系列的第三篇文章中,Daniel Robbins 向您显示了如何利用 OpenSSH 代理程序连接转发来增强安全性。他还共享 keychain shell 脚本近期的改进。 我们中的许多人都使用非常优秀的 OpenSSH 作为古老的 telnet和 rsh命令的替代品,OpenSSH 不仅安全而且是加密的。OpenSSH 更吸引人的特性之一是它能够使用以一对互补的数字式“密钥”为基础的 RSA 和 DSA 认证协议来认证用户。RSA 和 DSA 认证承诺不必提供密码就能够与远程系统建立连接,这是其主要魅力之一。有关更多背景资料,请参阅关于 OpenSSH 密钥管理的本系列文章中以前的几篇,分别包括 RSA/DSA 认证(第 1 部分)和 ssh-agent 和 keychain(第 2 部分)。 由于第 2 部分发表在 2001 年 9 月的 developerWorks上,并且稍后在 Slashdot 和 Freshmeat(请参阅本文后面的 参考资料,获取到这些站点的链接)上引用了此文,因此,许多人已经开始使用 keychain,而且它已经做了许多更改。我收到了世界各地开发人员编写的约 20 个高质量的补丁程序。我已将其中许多补丁代码合并入 keychain源码中,它目前的版本是 1.8(请参阅 参考资料)。我真诚地感谢所有提交补丁程序、错误报告、功能请求及感谢信的那些人。 加强 ssh安全性 在 上篇文章中,我花了一些时间来讨论运行 ssh-agent在安全性方面的利弊。第二篇文章发表在 developerWorks的几天后,我收到来自 Sarnoff Corporation 的 Charles Karney 的一封电子邮件,他非常礼貌地通知了我 OpenSSH 新的认证代理程序转发的能力,我们将会简要地讨论这一能力。另外,Charles 强调:在 不可信机器上运行 ssh-agent是十分危险的:如果有人成功地获取系统上的 root 访问权,那么就 能从 ssh-agent中抽取您解密的密钥。即使抽取密钥有一定的困难,但是它还是在专业的解密高手的能力范围之内。而且,基本事实就是偷窃私钥是 可能的,这意味着我们应首先采取措施来防止这种情况的发生。 为了简单描述保护私钥的策略,首先必须把我们访问的机器归为两种类型中的一类。如果特定主机是安全性良好或是孤立的 ― 要成功获取主机的 root 访问权几乎不可能 ― 那么,那台机器应被认为是 可信主机。不过,如果许多其他人使用这台机器或者您怀疑系统的安全性,那么这台机器应被认为是 不可信主机。为防止您的私钥被他人抽取,绝对不应在不可信主机上运行 ssh-agent(和由此启动的 keychain)。 那样的话,即使系统安全性受到威胁,由于 ssh-agent没有运行,闯入者在第一时间内也不能抽取密钥。 但是,这产生了一个问题。如果不能在不可信主机上运行 ssh-agent,那么如何从这些系统上建立安全的、无密码的 ssh连接呢?答案是:只在 可信主机上使用 ssh-agent和 keychain,并利用 OpenSSH 新的 认证转发能力将无密码的认证扩展到任何不可信主机上。简略地说,就是通过允许远程 ssh会话来联系运行在可信系统上的 ssh-agent,使认证转发工作。 要了解认证转发工作的原理,让我们首先看一下一个假设情况,其中用户 drobbins有一个称为 lappy的可信的便携式电脑、一个称为 trustbox的可信服务器和另外两个他必须访问的不可信系统,分别称为 notrust1和 notrust2。当前,他在所有这四台机器上都使用 ssh-agent以及 keychain,如下所示: 图 1. 运行在可信和不可信机器上的 ssh-agent 这种方法所带来的问题是如果有人获取 notrust1或 notrust2的 root 访问权,那么这个人当然可以从现在易受攻击的 ssh-agent进程中抽取密钥。为了解决这个问题, drobbins停止运行不可信主机 notrust1和 notrust2上的 ssh-agent和 keychain。事实上,为了更为小心, drobbins决定只在 lappy上使用 ssh-agent和 keychain。这样限制了他解密的私钥的泄露,同时防止他的私钥被偷窃: 图 2. ssh-agent 只运行在 lappy 上;一个更安全的配置 当然,这种方法带来的问题是 drobbins现在只能从 lappy建立无密码的连接。让我们看一下如何启用认证转发并解决这个问题。 假设所有机器都运行 OpenSSH 的最近版本,通过使用认证转发,我们能解决这个问题。认证转发允许远程 ssh进程联系您正在本地可信机器上运行的 ssh-agent― 而不要求在您正运行 ssh的同一台机器上运行 ssh-agent的一个版本。这通常允许您在单个机器上运行 ssh-agent(和 keychain),并且这意味着源于这台机器的所有 ssh连接(直接或间接)都将使用本地 ssh-agent。 为了启用认证转发,我们在 lappy和 trustbox的 /etc/ssh/ssh_config 中添加了下面行。请注意:这是 ssh的配置文件( ssh_config),而不是 ssh守护进程 sshd的配置文件( sshd_config): 清单 1. 将这行添加到 /etc/ssh/ssh_config 中
drobbins可以从 lappy连接到 trustbox,然后在不提供任何连接的密码的情况下,从 trustbox连接到 notrust1。这两个 ssh进程都“进入”运行在 lappy上的 ssh-agent: 清单 2. 进入 lappy
ssh-A替代原来单纯的 ssh来明确启用认证转发。这里是当我们使用上面提到的认证转发而登录到 trustbox和 notrust1时,实现此操作的内部运行图: 图 3. 正在运作的代理程序转发 正如您看到的,当 ssh连接到 trustbox时,它维持与运行在 lappy上的 ssh-agent的连接。当产生从 trustbox到 notrust1的 ssh连接时,这个新的 ssh进程维持与以前 ssh的认证连接,这样有效地延伸了链。这个认证链是否能延伸到 notrust1以外的其它主机取决于 notrust1的 /etc/ssh/ssh_config 是如何配置的。 只要启用了代理程序转发,通过使用在可信 lappy上运行的 ssh-agent,这个链上的所有部分都能认证。 认证转发提供了许多在此没有提到的安全性优点。为了让我相信代理程序连接转发的重要性,Charles Karney 与我分享了以下三个安全性优点: 私钥只存储在可信机器上。这样防止怀有恶意的用户从磁盘获取加密的密钥并防止他们试图解加密。 ssh-agent只运行在可信机器上。这样防止闯入者进行远程 ssh-agent进程的内存转储并从转储中抽取出您的解密私钥。 由于您只需要在可信机器上输入密码,所以防止了任何击键记录器在您输入密码时悄悄地截取密码。 使用认证代理程序连接转发的一个缺点是:它不能解决允许 cron 作业利用 RSA/DSA 认证这个问题。解决这个问题的一个方案是设置所有需要 RSA/DSA 认证的 cron 作业,这样它们就可以从局域网中的一台可信机器上执行。如果需要的话,这些 cron 作业能使用 ssh连接到远程系统来实现自动备份、使文件同步等操作。 既然我们已经了解了认证代理程序连接转发,那么让我们转到近期对 keychain脚本本身所做的改进上。 感谢用户发来补丁程序,许多重要的改进已添加到 keychain源码中。 用户提交的 keychain补丁程序中有几个与功能有关。例如,您应记得 keychain创建了一个 ~/.ssh-agent 文件;这个文件的名字现在已经改为 ~/.ssh-agent-[hostname],这样 keychain可以使用从几个不同物理主机上能访问已挂装 NFS 的主目录。除了 ~/.ssh-agent-[hostname] 文件外,现在还有一个 ~/.ssh-agent-csh-[hostname] 文件,兼容 csh的 shell 利用 source 命令读入并执行该文件。最后,添加了一个新的 --nocolor选项,这样,如果您碰巧在使用不兼容 vt100 的终端时,就能禁用彩色化功能部件。 当完成了许多重要的功能改进时,对 shell 兼容性问题也做了大量的修正。您看,keychain 1.0 需要 bash,而以后的版本则改为可以使用任何 sh兼容的 shell。这一更改使得 keychain跳出固有的框架,可以在包括 Linux、BSD、Solaris、IRIX 和 AIX 以及其它 UNIX 平台的几乎所有 UNIX 系统上运行。转至 sh并与常规 UNIX 兼容,这已经是困难重重了,而同时它也经过了大量的学习经验。创建运行在所有这些平台上的单个脚本事实上是非常棘手的,主要因为我根本无权访问这些操作系统中的大多数系统!要感谢的是,全球范围内的 keychain用户这样做了,并且许多人在识别兼容性问题以及提交补丁程序来解决它们等方面提供了非常大的帮助。 事实上,有两类兼容性问题必须解决。首先,我需要确信 keychain只使用所有 sh实现下完全支持的内置件、表达式和操作符,包括所有流行的免费和商业 UNIX shshell、 zsh(以 sh兼容的模式)和 bash版本 1 和 2。这里是用户提交的应用到 keychain源码中的一些 shell 兼容的修正: 由于较早的 shshell 不支持 ~约定来引用用户的主目录,因此将使用 ~的行更改为使用 $HOME来代替: 清单 3. 使之成为 $HOME
source的引用都更改成 .,以确保与纯 NetBSD 的 /bin/sh兼容,因为它根本不支持 source命令: 清单 4. 迎合 NetBSD
touch foo来“更新”文件的修改日期,您可以这样做: 清单 5. 更新文件的修改日期
fork(),而脚本却变得更加有效。 > foo应使用任何兼容 sh的 shell;但是,好象 ash并不支持它。对大多数人来说这不应是个问题,因为 ash更象是急救磁盘类型的 shell,而不是人们每天都要使用的程序。 获取在多个 UNIX 操作系统下运行的脚本不单单需要坚持纯粹的 sh语法。请记住,大多数脚本还要调用诸如 grep、 awk、 ps和其它命令的外部命令,而且必须尽可能以与标准相符的方法来调用这些命令。例如,包含在大多数 UNIX 版本中的 echo能识别 -e选项,而 Solaris 中的 echo却不能识别 ― 当使用它时,它只把 -e打印到标准输出(stdout)。因此为了处理 Solaris, keychain现在自动检测 echo -e是否起作用: 清单 6. 寻找 Solaris
-e,那么将 E设置为 -e。然后,可以按如下所示调用 echo: 清单 7. 更好的 echo
echo $E,而不是 echo -e,可以根据需要动态地启用或禁用 -e选项。 pidof,ps 可能最重要的兼容性修正涉及到更改 keychain如何检测当前正在运行的 ssh-agent的进程的方法。以前,我使用 pidof命令来这样做,但是由于有几个系统没有 pidof,所以不得不抛弃这个方案。实际上, pidof无论如何都不是最佳的解决方案,因为它列出系统上运行的 所有 ssh-agent进程,而不管用户是谁,但我们实际上感兴趣的是当前有效的 UID 所拥有的所有 ssh-agent进程。 所以,为抽取所需的进程标识,我们不使用 pidof,而是转向将 ps输出通过管道输送到 grep和 awk上。 这是一个用户提交的修正: 清单 8. 管道比 pidof 好
mypids变量设置为当前用户拥有的所有 ssh-agent进程的值。 grep -v grep命令是管线的一部分,这样确保 grep ssh-agent进程不会成为我们的 PID 列表中的一部分。 这种方法从概念上来说非常好,但是因为 ps选项未在各类 BSD 和 System V 的 UNIX 派生系统上标准化,所以使用 ps开启了一个全新的尚未解决的难题。这里是一个示例:虽然 ps uxw在 Linux 下起作用,而在 IRIX 下不起作用。 ps -u username -f在 Linux、IRIX 和 Solaris 下起作用,而在只理解 BSD 样式的 ps选项的 BSD 下不起作用。为了解决这个问题,在执行 ps管线之前, keychain会自动检测当前系统的 ps是使用 BSD 语法或还是 System V 语法: 清单 9. 检测 BSD 还是 System V
ps命令,脚本试着运行 ps uxw,而丢弃任何输出。如果这个命令的错误码为零,那么我们知道 ps uxw正常工作,并且我们正确地设置了 psopts值。但是,如果 ps uxw返回一个非零的错误码(指出我们需要使用 BSD 样式的选项),那么我们试着运行 ps -u `whoami` -f,并再次丢弃了任何输出。此时,我们有希望发现可以使用的 ps是 BSD 的变体还是 System V 的变体。如果我们不知道答案,那么打印出错误并退出。但是很有可能这两个 ps命令中的一个工作正常,在这样的情况下,执行上面代码段的最后一行,即 ps管线。通过紧跟在 ps后面使用 $psopts变量扩展,我们能将正确的选项传送给 ps命令。 ps管线还包含一个 grep,它的确是一个宝物,是 Hans Peter Verne 好心发给我的。 请注意 grep -v grep不再是管线的一部分;实际上它已经被除去并且 grep "ssh-agent"已经改为 grep "[s]sh-agent"。这样一个 grep命令最后执行与 grep ssh-agent | grep -v grep相同的操作;您知道为什么吗? 清单 10. 简洁的 grep 诀窍
grep "ssh-agent"和 grep "[s]sh-agent"应匹配完全相同的文本行的话,那么您是正确的。所以当 ps的输出通过管道输送给它们时,为什么它们生成不同的结果呢?这里是它的工作原理:当使用 grep "[s]sh-agent"时,您更改了 grep命令在 ps进程列表中显示的方式。通过这样做,防止 grep与它本身相匹配,因为 [s]sh-agent字符串与 [s]sh-agent正则表达式不匹配。那样不是很完美吗?如果您仍不太明白,请用一下 grep,您很快就会明白了。 本专栏文章对讨论的 OpenSSH 作出了结论。希望您已经学到了有关 OpenSSH 的很多知识,足以开始使用 OpenSSH 来保护您系统的安全。 您可以参阅本文在 developerWorks 全球站点上的 英文原文. “ 通用线程:OpenSSH 密钥管理,第 1 部分”( developerWorks,2001 年 7 月)涵盖了 RSA/DSA 认证。 “ 通用线程:OpenSSH 密钥管理,第 2 部分”( developerWorks,2001 年 9 月)介绍了 ssh-agent 和 keychain。 在 Gentoo Linux Keychain 页面上可以获得 keychain的最新版本 。 请务必访问 OpenSSH 的开发主页,并查阅 OpenSSH 常见问题解答。 您可以从 Openbsd.org 下载最新的 OpenSSH 源码 tarball 和 RPM。 PuTTY是用于 Windows 机器上的一个出色的 ssh客户程序。 “SSH, The Secure Shell: The Definitive Guide”(O'Reilly & Associates,2001)一书可能会对您有帮助。 作者的网站上有关于这本书、常见问题解答、新闻和更新等信息。 请访问 Slashdot,获取“面向初学者的新闻和其它相关内容”。 请查阅 Freshmeat,在开放源码包的新发行版出现时它就列出来它们。 请浏览 developerWorks上 更多 Linux 参考资料。 请浏览 developerWorks上 更多开放源码资料。
|
相关文章推荐
- OpenSSH 密钥管理,第 1 部分
- OpenSSH 密钥管理,第 2 部分
- 通用线程: OpenSSH 密钥管理,第 1 部分
- 通用线程: OpenSSH 密钥管理,第 1 部分
- 通用线程: OpenSSH 密钥管理,第 2 部分
- Linux 下的一个全新的性能测量和调式诊断工具 Systemtap, 第 3 部分: Systemtap
- 用 Hadoop 进行分布式并行编程, 第 3 部分
- 掌握 Ajax,第 3 部分: Ajax 中的高级请求和响应
- LAMP 系统性能调优,第 3 部分: MySQL 服务器调优
- Java 8 习惯用语,第 3 部分 传统 for 循环的函数式替代方案
- 应用程序架构本质,第 3 部分: 软件开发方法学入门(转)
- Vim 实用技术,第 3 部分: 定制 Vim
- 使用 XML: UML、XMI 和代码生成,第 3 部分
- Bash 实例,第 3 部分探讨 ebuild 系统
- 使用 XForms 和 Ruby on Rails 开发小型门诊管理系统,第 3 部分:实现护士和医生 XForm
- 用 Hadoop 进行分布式并行编程,第 3 部分
- 浅析 Linux 中的时间编程和实现原理,第 3 部分: Linux 内核的工作
- SWT 和 JFace, 第 3 部分:了解 TabFolder、Canvas、StyledText 和其他多种控件
- Eclipse 中的 JFace 数据绑定,第 3 部分: 使用高级功能(8/19)
- 转自IBM学习 浅析 Linux 初始化 init 系统,第 3 部分 Systemd