如何在Linux上最妥善地管理加密密钥?
存储SSH加密密钥和牢记密码可能是一件让人很头痛的事儿。不过遗憾的是,在如今恶意黑客和漏洞猖獗的年头,做好基本的安全防范措施是必不可少的做法。对于许多普通用户来说,这就意味着只是牢记密码,可能还要找到一款存储密码的优秀软件,因为我们提醒普通用户不要每个网站都使用一样的密码。但是对于从事不同IT行业领域的我们这些人来说,我们就需要在此基础上更进一步。我们还要处理SSH密钥之类的加密密钥,而不仅仅是密码。
一种场景如下:我在云上运行一台服务器,用于我的主git软件库。我有好多台办公用的计算机。所有那些计算机都需要登录进入到那台中央服务器,以便推送和获取内容。我设置了git以便使用SSH。git使用SSH时,git登录进入到服务器的方式实际上与启动命令行、使用SSH命令接入到服务器一样。为了配置一切,我在.ssh目录中创建了一个配置文件,里面含有的Host项提供了服务器名称、主机名称、登录用户以及密钥文件路径。然后,我只要输入下列命令,就可以测试一下这个配置:
ssh gitserver
很快我就看到了服务器的bash外壳。现在,我可以配置git,使用这同一个项,用存储的密钥登录进去。容易得很,除了有一个问题:对于用来登录进入到那台服务器的每台计算机而言,我都需要有一个密钥文件。这意味着会有不止一个密钥文件。我在这台计算机上有几个这样的密钥,在其他计算机上有几个这样的密钥。正如普通用户有无数个密码那样,我们IT人员到头来很容易会有无数个密钥文件。这该如何是好?
清理乱局
在开始使用一款软件帮助管理密钥之前,你得做好一些基础工作,弄清楚应该如何处理密钥、我们提出的问题到底是否合理。而这首先需要你明白自己的公钥放在哪里、私钥又放在哪里。假设你已知道下列这些:
1. 公钥与私钥的区别
2. 为什么无法利用公钥生成私钥,但是却可以利用私钥生成公钥。
3. authorized_keys文件的用途以及它放在何处。
4. 你如何使用私钥,登录进入到在authorized_keys文件中有对应公钥的服务器。
这里有个例子。你在亚马逊网络服务(AWS)平台上创建一台云服务器时,就得提供一个SSH密钥,用来连接到你的服务器。每把密钥都有公开部分和私密部分。因为你希望自己的服务器保持安全,乍一看,你似乎把私钥放在那台服务器上,并将公钥贴身带着。毕竟,你不希望那台服务器可以公开访问,不是吗?但其实正好相反。
保管那把私钥,并放在身边,而不是放在某台远程服务器上。
你把公钥放在AWS服务器上,牢牢保管用来登录进入到服务器的私钥。你保管那把私钥,并放在身边,而不是放在某台远程服务器上,如上图所示。
原因如下:即便公钥被别人知道了,他们也无法登录进入到服务器,因为他们没有私钥。此外,如果有人确实设法闯入了你的服务器,他们发现的只是公钥。无法利用公钥生成私钥。所以,如果你在其他服务器上使用同样这个密钥,他们无法用该密钥来登录进入到其他那些计算机。
这就是为什么你把公钥放在自己的服务器上,用来通过SSH登录进入到服务器。私钥是你贴身带着的。你不允许那些私钥落到别人手里。
但是仍然有问题。以我的git服务器为例。我要做几个决定。有时候,我登录进入到托管在别处的开发服务器。在那台开发服务器上,我需要连接到我的那台git服务器。开发服务器如何才能连接到git服务器?通过使用私钥。而这里就存在问题。这种场景需要我把私钥放在托管在别处的服务器上,这么做可能很危险。
现在看看进一步的场景:如果我使用单一密钥登录进入到多台服务器,会怎样?如果入侵者设法弄到了这样一把私钥,他有了该私钥后可以进而访问整个服务器虚拟网络,准备搞一些严重的破坏。这可不是什么好事。
而这当然引出了另一个问题:我是否应该对另外那些服务器使用同一把密钥?就像我刚才描述的那样,这可能很危险。
最后,这听起来一团糟,不过有一些简单的解决办法。不妨逐一介绍。
(注意:除了仅仅登录进入到服务器外,还有许多地方要用到密钥,不过我介绍这一种场景是为了表明你在处理密钥时面临的问题。)
重视通行码
你在创建密钥时,可以选择添加通行码(passphrase),使用私钥时需要通行码。有了这个通行码,私钥文件本身使用通行码来加密。比如说,如果你将公钥存储在服务器上,使用私钥登录进入到该服务器,就会看到输入通行码的提示。要是没有通行码,密钥就没法使用。另外,你可以配置私钥,一开始没有通行码。那样,你只需要登录进入到服务器的密钥文件。
对用户来说通常不用通行码更容易,但是我强烈建议在许多情况下使用通行码,一个理由是,如果私钥文件被偷,偷走文件的人还是没法使用它,除非他能查明通行码。从理论上来说,这可以为你赢得时间,因为你可以在攻击者发现通行码之前将公钥从服务器上删除,因而保护系统。使用通行码还有其他理由,不过光这个理由就值得我在许多情况下使用它。(举例说,我在安卓平板电脑上装有VNC软件。平板电脑存有我的私钥。如果平板电脑被偷了,我可以立即从平板电脑登录进入的服务器废除公钥,让私钥毫无用处,有没有通行码都没有关系。)不过在一些情况下,我并不使用通行码,因为我登录进入的服务器可能没有太多的宝贵数据在上面。这要看具体情况。
服务器基础设施
你如何设计服务器基础设施将影响到如何管理密钥。比如说,如果你有多个用户要登录,就需要确定每个用户是否获得单独的密钥。(通常来说,他们应该获得单独的密钥;你不希望用户共享私钥。那样一来,如果某个用户离开了企业或者失去了信任,你就可以废除该用户的密钥,没必要为另外每个用户生成新密钥。同样,如果共享密钥,他们就能以彼此的身份登录进去,这同样不好。)但是另一个问题是,你如何分配服务器。比如说,你使用某种工具(比如Puppet)来分配许多服务器吗?是否基于自己的映像来创建多台服务器?如果你复制服务器,每台服务器是否需要有同样的密钥?不同的云服务器软件让你可以配置这方面,具体看你怎么选择了。可以让服务器获得同一密钥,也可以为每台服务器生成新的密钥。
如果你处理的是复制的服务器,要是用户需要使用不同的密钥登录进入到两台其他方面相似的不同服务器,就会让人犯晕。但是另一方面,让几台服务器共享同一密钥存在安全风险。或者另一方面,如果你的密码需要用于登录之外的用途(比如挂载加密的驱动器),那么你就需要同一密钥在多个地方。正如你所见,是否需要在不同的服务器上使用同一密钥不是我可以为你做出的决定;有一些地方需要取舍,你要自行决定什么最合适。
最后,你可能会有:
•需要登录进入的多台服务器;
•登录进入不同服务器的多个用户,每个用户有各自的密钥;
•每个用户有多把密钥,以便登录进入到不同的服务器。
(如果你在其他情况下使用密钥――你可能会这样,说到如何使用密钥,需要多少密钥,是否共享密钥以及你如何处理密钥的公共部分和私密部分,同样的基本概念仍会适用。)
安全方法
知道自己的基础设施和独特情况后,你就需要制定一项密钥管理方案,帮助你指导如何分发和存储密钥。比如说,正如前文所述,如果我的平板电脑被偷,但愿平板电脑被用来访问服务器之前,我可以从服务器上废除公钥。正因为如此,我在总体计划中需要考虑到下列情况:
1. 私钥存放在移动设备上没关系,但是它们必须包通行码。
2. 必须有一种方法可以从服务器迅速废除公钥。
在你的情况下,你可能决定根本不想要为频繁登录的系统使用通行码;比如说,系统可能是开发人员每天登录好多次的测试机器。那很好,但是那样的话你就需要稍微调整一下规则。你可能要添加一条规则,规定不得从移动设备登录进入到该机器。换句话说,你需要根据自己的情况来制定规程,而不是想当然地认为有一应俱全的做法。
软件
再来说说软件。奇怪的是,没有许多优秀而可靠的软件解决方案用来存储和管理你的私钥。考虑这一点:如果有一款软件为你的所有服务器存储所有密钥,该软件又由一个快捷密码所保护,你的密钥果真安全吗?或者类似的是,如果你的私钥放在硬驱上以便SSH软件快速访问,密钥管理软件果真提供得了任何保护吗?
但是就整个基础设施和创建及管理公钥而言,还是有一些解决方案。我已经提到了Puppet。在Puppet界,你可以创建模块,以不同的方式来管理服务器。其想法在于,服务器是动态的,未必是彼此的精确副本。这里有一种巧妙的方法:http://manuel.kiessling.net/2014/03/26/building-manageable-server-infrastructures-with-puppet-part-4/,在不同服务器上使用同一密钥,但是为每个用户使用不同的Puppet模块。这种解决办法可能适合你,也可能不适合你。
或者,另一种办法就是完全改弦易辙。在Docker界,你可以采取一种不同的方法,关于SSH和Docker的这篇博文作了详细介绍:http://blog.docker.com/2014/06/why-you-dont-need-to-run-sshd-in-docker/。
但是管理私钥怎么样?如果你搜索一下,找不到许多软件方案,我在上面提到了原因;私钥放在你的硬驱上,管理软件可能无法提供太多的额外安全。但是我确实使用这种方法来管理密钥:
首先,我在.ssh/config文件中有多个Host项。我有一个项用于登录的主机,但是有时候我有多个项用于单个主机。如果我要多次登录,就会出现这种情况。我有两种不同的机制来登录托管git软件库的那台服务器;一种完全用于git,另一种用于一般用途的bash访问。用于git的那种登录大大限制���那台机器上的权限。还记得我前面说的放在远程开发机器上的git密钥吗?虽然那些密钥可以用来登录进入到我的其中一台服务器,但使用的帐户受到了严重限制。
其次,大多数这些私钥包括通行码。(如果遇到非要多次输入通行码,可以考虑使用ssh-agent。)
第三,我确实有一些服务器想更认真一点地得到保护,我在Host文件中没有对应的项。这更像是社会工程学层面,因为密钥文件仍在那里,但是需要入侵者花更长一点的时间来找到密钥文件,弄清楚对哪台机器下手。那种情况下,我只要手动输入长长的ssh命令(这其实不是那么差劲)。
你能看到,我并不使用任何特殊软件来管理这些私钥。
没有一应俱全的做法
我们偶尔会接到读者抛出的问题,问有什么好的软件可用于管理密钥。但是不妨先冷静想一想。这个问题其实需要用不同的方式来表达,因为根本不存在一应俱全的解决方案。你应该根据自己的情况提出问题。你只是试图找个地方来存储密钥文件?还是在寻找一种办法来管理多个用户,每个用户有各自的公钥,这些公钥又需要插入到authorized_keys文件?
我在这篇文章中介绍了基本方面,但愿现在你能明白,只有你提出了正确的问题,才知道如何管理密钥,以及应该寻找什么样的软件(如果你果真需要额外软件的话)。
英文:How to Best Manage Encryption Keys on Linux