如何在UbuntuVPS上使用Monkeysphere验证SSH服务器身份
介绍
随着组织的发展,管理大量 SSH 密钥和服务器可能会非常困难。 在整个组织中正确识别有效密钥并删除无效密钥可能会充满错误,并对您的服务器安全产生巨大影响。
此外,当服务器发生变化时,有时您的用户会收到无法确定服务器真实性的警告。 大多数用户在连接之前不会仔细检查服务器的密钥指纹,从而允许有人可能欺骗服务器并执行中间人攻击。
创建了一个名为 monkeysphere 的项目来解决这些问题。 它通过利用 GPG 密钥和信任网络模型来验证服务器的凭据并提供简单的用户管理来做到这一点。
在本指南中,我们将讨论如何设置 monkeysphere 以便向用户验证您的服务器。 这将解决用户不得不猜测他们正在连接的服务器是否实际上是他们正在尝试访问的服务器的问题。 通常,当您第一次连接到服务器时,您会看到如下所示的内容:
The authenticity of host '107.170.43.127 (107.170.43.127)' can't be established. ECDSA key fingerprint is 10:14:75:d6:42:a3:c5:59:d1:83:6d:cf:52:61:4a:52. Are you sure you want to continue connecting (yes/no)?
我们将在本文中努力避免向我们的用户显示这些消息。 在以后的指南中,我们将讨论 如何解决轻松识别和验证用户的问题 。
我们将使用 Ubuntu 12.04 VPS 实例来配置这个系统。 我们将有一个 SSH 服务器,我们将尝试向我们的用户验证。 我们还需要另外两台机器来演示(无论是本地计算机还是 VPS 实例)。 一台是管理员的计算机,另一台是我们将用作测试机器的客户端,以查看我们的信任网络是否允许它验证服务器的身份。
基本策略
整个monkeysphere 系统依赖GPG 密钥和密钥服务器来运行。 在我们开始之前,您必须为每个系统配置这些密钥。 许多实际配置也将通过这些键完成。
在开始使用 GPG 之前,您可能需要查看我们关于 如何使用 GPG 密钥 的文章。 我们将为您提供所需的特定命令,但更深入地了解正在发生的事情可能会帮助您在出现问题时进行故障排除。
我们的三台机器及其用途将是:
- server.example.com:我们要向客户端验证的 SSH 服务器。
- admin.example.com:我们将用于配置访问权限的管理员计算机。 这通常是您的家用计算机,但我们将在我们的指南中使用另一个 Droplet。
- client.example.com:这是我们将用来测试验证的客户端。 我们希望这台计算机能够连接到服务器而不会收到未知主机警告。
SSH 服务器机器应该有一个可公开访问的域名。 使用本指南 在 DigitalOcean 上设置域名。
对于第一部分,我们要在管理员和客户端计算机上生成密钥。 然后,我们会将这些密钥上传到集中式密钥服务器。 我们将从密钥服务器中提取管理员的密钥,并使用客户端密钥对其进行签名和信任,这表明我们的客户端信任我们的管理员。
这是整个验证方案的基础。 我们不是信任计算机或密钥,而是利用 GPG 的信任网络模型。 如果您认为某人对您尝试连接的服务器知识渊博且值得信赖,您可以让该人让您知道服务器是否合法。 在这种情况下,我们的客户端将相信服务器管理员可以验证服务器的身份。
然后,我们可以配置 monkeysphere 以使用 GPG 框架来拉取信息,以验证我们信任的管理员是否为我们尝试连接的服务器提供担保。
设置 GPG 密钥和身份验证
幸运的是,GPG 默认安装在 Ubuntu 上。
我们将首先在我们的客户端系统和管理员系统上创建一些 GPG 密钥。 这些密钥与单个用户相关联,用于全局识别该用户。 每个需要访问您的 SSH 服务器的人都应该拥有识别他们的 GPG 密钥。 这就是我们建立信任网络的方式。
生成 GPG 密钥
我们需要在客户端机器和管理员机器上创建一个 GPG 密钥。 在这些计算机的 两台 上执行以下操作:
gpg --gen-key
这将提示您提出一些问题来创建您的密钥对。 首先,它会询问您希望创建哪种类型的密钥。 选择“1”创建两个 RSA 密钥。 接受下一个问题中的默认值以生成 2048 位密钥。 选择“0”使密钥永不过期,然后键入“Y”确认信息正确。
接下来,系统会要求您提供每个用户的信息。 我们将使用名称“admin”和电子邮件地址“admin@fakedomain.com”作为管理员密钥。 对于我们的客户,我们将使用名称“client”和电子邮件“client@fakedomain.com”。 你有机会添加一个可选的评论,然后你应该输入“O”来表示信息是好的。
输入并确认密码以保护密钥。
计算机现在将使用从系统收集的随机数据创建密钥。 这称为“熵”,用于创建真正的随机密钥。 可能需要一段时间。 有时,使用单独的 SSH 会话登录来做一些工作以加快进程会很有帮助。
生成密钥后,它将存储在您的 GPG 密钥环中。 您可以通过键入以下内容来查看它:
gpg --list-keys
/root/.gnupg/pubring.gpg
pub 2048R/ 08D014B3 2014-03-14 uid 客户端 @假域名 .com> 子 2048R/4C73683E 2014-03-14
上面红色部分是缩短的密钥 ID。 我们可以使用这个散列来引用这个键。
我们应该将我们的密钥上传到密钥服务器。 这些密钥服务器在世界各地复制,允许任何人提取我们的密钥信息。 这就是我们想要的,因为它允许我们的两个用户和 SSH 服务器相互交互并建立信任关系。
要将我们的密钥上传到密钥服务器,在我们的客户端和管理员计算机上,我们需要输入类似这样的内容。 我们将需要上面提到的密钥 ID:
gpg --send-key key_id
因此,对于我们上面的客户端密钥,我们可以通过键入以下内容将其上传到密钥服务器:
gpg --send-key 08D014B3
签署密钥
现在我们的管理员和我们的客户都拥有 GPG 密钥并将它们上传到密钥服务器,它们将开始传播到世界各地的其他密钥服务器。 将每个密钥复制到世界各地的 GPG 服务器可能需要一些时间,因此您可能需要等待几分钟才能使这些步骤生效。
等待几分钟后,您可以尝试在每台计算机上拉下相反的键。 这意味着,在客户端计算机上,尝试下拉管理员的密钥。 您还应该下拉管理员计算机的客户端密钥。
我们将对这些密钥进行签名,这意味着我们认为它们是有效的,并且已经验证它们是我们试图识别的人的正确密钥。 为了绝对确保您获得正确的密钥,我们将通过指纹识别来指定 exact 密钥,无需搜索即可执行此操作。
在您的客户端服务器上,通过键入此命令获取 GPG 密钥的指纹。 “客户”是您在构建密钥时选择的名称或电子邮件地址:
gpg --with-colons --fingerprint 客户端
tru::1:1394819815:0:3:1:5 pub:u:2048:1:4B3F73E208D014B3:2014-03-14:::u:client @假域名 .com>::scESC: fpr::::::::: 85ECDB498FB0CAB5F02989E64B3F73E208D014B3 : sub:u:2048:1:254105194C73683E:2014-03-14::::::e:
上面突出显示的输出部分是您要查找的指纹。
现在你有了这个指纹,在你的管理员的电脑上,你可以告诉 GPG 用那个指纹寻找一个钥匙,然后把它拉到本地电脑上,像这样:
gpg --recv-keys 85ECDB498FB0CAB5F02989E64B3F73E208D014B3
这将连接到默认密钥服务器并请求由该指纹识别的密钥。 它将被转移到我们的本地系统中。
现在我们可以访问密钥,我们可以对其进行签名以表明我们作为管理员信任属于客户端的密钥:
gpg --sign-key 85ECDB498FB0CAB5F02989E64B3F73E208D014B3
现在,我们已经在本地系统上签署了密钥。 我们现在应该将客户端的密钥发送回密钥服务器。 密钥服务器将更新其关于客户端密钥的信息,以表明我们的管理员帐户已签署该密钥并认为它有效。
要将签名密钥发送回密钥服务器,我们键入:
gpg --send-key 85ECDB498FB0CAB5F02989E64B3F73E208D014B3
就像以前一样,密钥服务器现在拥有我们的管理员密钥和客户端密钥。 不同之处在于密钥服务器 also 现在具有来自客户端密钥上的管理员密钥的签名。
我们现在需要做相反的操作(用客户端密钥签署管理员密钥)。 为此,在管理员的机器上,我们获取管理员密钥指纹:
gpg --with-colons --fingerprint admin
现在,在客户端机器上,我们使用从输出中收集的指纹来下拉、签名,然后上传管理员密钥,就像我们之前所做的那样:
gpg --recv-keys 7C873BB244245CB13BFEFC31F7C66E2FF945A061 gpg --sign-key 7C873BB244245CB13BFEFC31F7C66E2FF945A061 gpg --send-key 7C873BB244245CB13BFEFC31F7C66E2FF945A061
之后,在 两台 机器上,我们需要刷新我们的密钥。 这是因为我们的每个用户都签署了他们的密钥,但他们在自己的计算机上没有该签名,只是在对面计算机和密钥服务器上。 您需要在这里等待几分钟,让您的更改传播,然后键入:
gpg --refresh-keys
您需要验证更新是否已处理。 输出应该有一行写着“新签名:1”。 如果不存在,请重试直到它出现。
现在,您的每台计算机都应该有两个签名密钥。
相信管理员的判断
为了让我们的信任网络真正起作用,我们不仅要让客户端签署管理员的密钥,我们还必须确定客户端“信任”管理员的判断。
这意味着当管理员说 SSH 服务器是它所说的机器时,我们作为客户端可以信任管理员 另一个人 所做的签名。
首先,我们可以通过键入以下内容查看客户端上的当前设置:
gpg --check-trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model gpg: depth: 0 valid: 1 signed: 1 trust: 0-, 0q, 0n, 0m, 0f, 1u gpg: depth: 1 valid: 1 signed: 0 trust: 1-, 0q, 0n, 0m, 0f, 0u
这是一组非常混乱的信息。 第一行说明了我们正在运行的信任模型。 基本上,如果我们有一个由我们完全信任的用户签名的密钥,那么我们将认为该密钥也是有效的。 如果密钥由至少 3 个我们只是勉强信任的人签名,我们也可以信任它。
第二行告诉我们我们的“深度 0”信任级别。 这基本上是关于我们自己的密钥的信息。 我们认为它有效并已签名。 “信任”部分告诉我们,密钥属于“u”类别,表示最终受信任。
第三行告诉我们关于“深度 1”的键。 这些是我们亲自签名的密钥。 我们可以看到我们认为一个密钥是有效的(我们签署了管理员密钥以使其有效),并且管理员密钥没有签署任何我们关心的其他密钥。
在该行的信任部分,我们有一个带有“1-”的字段。 这意味着我们在此级别拥有的一个密钥(管理员密钥)尚未获得信任设置。 我们不知道该密钥的信任级别。
我们希望完全信任管理员密钥。 这样,管理员签署的任何密钥(例如我们试图验证其身份的 SSH 服务器)都将被我们视为合法的。 为此,我们可以通过键入以下内容来更新客户端计算机上的信任数据库:
gpg --update-trustdb
您将被要求为您已签名但当前没有信任值的任何密钥分配信任等级。 它看起来像这样:
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model gpg: depth: 0 valid: 1 signed: 1 trust: 0-, 0q, 0n, 0m, 0f, 1u No trust value assigned to: 2048R/49E95F19 2014-03-14 "admin <admin@fakedomain.com>" Primary key fingerprint: A612 56B8 5307 B7ED 9AD8 D93E 9E06 881E 49E9 5F19 Please decide how far you trust this user to correctly verify other users' keys (by looking at passports, checking fingerprints from different sources, etc.) 1 = I don't know or won't say 2 = I do NOT trust 3 = I trust marginally 4 = I trust fully s = skip this key q = quit Your decision?
我们想完全信任这个密钥,所以输入“4”。
现在,由于我们相信管理员的判断,我们可以合理地确定管理员签名的密钥与相关用户或服务合法关联(通常我们会使用真实姓名而不是客户或管理员)。
安装 Monkeysphere 并配置 SSH 服务器
现在我们已经用他们的 GPG 密钥设置了我们的客户端和管理员计算机,我们可以开始实际的 monkeysphere 安装和配置。
Ubuntu 的默认存储库中有一个 monkeysphere 包。 它包含 SSH 使用 GPG 进行验证所需的服务器和客户端实用程序。 因此,我们需要在每台计算机上安装该软件包。
在此模型中的所有计算机(管理员、客户端、SSH 服务器)上,通过键入以下命令安装 monkeysphere:
sudo apt-get update sudo apt-get install monkeysphere
我们现在拥有将这些部分组合在一起所需的组件。 在 SSH 服务器上,我们将使用 monkeysphere 中包含的包装实用程序生成一个特殊的 GPG 密钥。 生成的密钥将基于用于向客户端标识服务器的 ssh_host_rsa_key
。
在 SSH 服务器上,键入:
monkeysphere-host 导入密钥 /etc/ssh/ssh_host_rsa_key ssh:// server.example.com
上面的第二个组件应该指示 SSH 服务器的域。 这将帮助客户端在尝试验证服务器连接时找到正确的服务器密钥。
现在,我们可以再次将刚刚创建的密钥上传到公钥服务器。 这一次,我们将再次使用包含在 monkeysphere 套件中的包装程序:
monkeysphere-host publish-key
这将上传您的服务器密钥并使其可供希望连接的客户端使用。
以服务器管理员身份验证服务器密钥
现在,我们将 SSH 服务器的密钥传播到全球的密钥服务器。 但这对我们有什么帮助?
好吧,GPG 的工作方式是建立所谓的“信任网络”。 简而言之,它的工作原理是建立一个您认识的人的个人网络,并且您可以高度确定地验证他们的身份。 然后,它使用这些信任关系让您将了解信息的责任转移给您信任的人。
在我们的案例中,我们(作为本示例的客户端)正在将了解服务器是否合法的责任转嫁给我们信任的管理员。 服务器的管理员应该清楚服务器的凭据是否签出。
所以我们现在需要做的就是以服务器管理员的身份签署 SSH 服务器的 GPG 密钥,这将允许我们的客户端用户通过信任管理员来验证服务器的身份。
在 SSH 服务器上,输入以下命令获取 GPG 指纹:
monkeysphere-host show-key
pub 2048R/0D281337 2014-03-14 uid ssh://fakedomain.com OpenPGP fingerprint: E06A426459E584F272DB708AD2D462790D281337 ssh fingerprint: 2048 61:1e:a7:66:1d:04:64:80:3f:27:81:34:31:78:8d:df (RSA)
“OpenPGP 指纹”与我们的 GPG 指纹相同。 这就是我们将用来提取管理员计算机的密钥并对其进行签名的方法。
在我们管理员的计算机上,键入此命令以获取 SSH 服务器的密钥。 同样,您可能需要等待几分钟:
gpg --recv-key E06A426459E584F272DB708AD2D462790D281337
我们将签署密钥,就像我们在上面使用客户端密钥所做的那样:
gpg --sign-key E06A426459E584F272DB708AD2D462790D281337
最后,我们需要记住将签名的密钥上传回密钥服务器:
gpg --send-key E06A426459E584F272DB708AD2D462790D281337
从客户端验证 SSH 服务器的身份
现在,我们已经准备好从客户端计算机验证 SSH 服务器的身份。
为此,我们必须将 SSH 命令包装在一个 monkeysphere 实用程序中。 这将告诉我们的客户端使用 monkeysphere 来检查我们尝试 ssh 进入的服务器的 GPG 密钥。 然后它将查看我们是否信任已确认服务器有效的任何人。
我们将第一次手动执行此操作,以向您展示正在发生的事情。 之后,我们可以将其添加到文件中以自动执行此操作。
在客户端上,键入如下手动命令:
ssh -oProxyCommand='monkeysphere ssh-proxycommand %h %p' server.example .com
-------------------- Monkeysphere 警告 ------------------- Monkeysphere 找到了该主机名的 OpenPGP 密钥,但是没有一个具有完全有效性。 找到与主机提供的 ssh 密钥匹配的 OpenPGP 密钥: pub 2048R/0D281337 2014-03-14 uid [未知] ssh://server.example.com sig!3 0D281337 2014-03-14 ssh://fakedomain.com RSA 密钥指纹为 61:1e:a7:66: 1d:04:64:80:3f:27:81:34:31:78:8d:df。 -------------------- ssh 下面继续-------- 主机的真实性' server.example.com ( )' 无法成立。 ECDSA 密钥指纹为 78:50:80:60:2a:a3:51:51:37:9d:25:8b:d4:0c:d1:15。 您确定要继续连接(是/否)?
在此处输入“否”。
如您所见,我们通常会收到关于无法确定我们尝试连接的主机的真实性的消息。 我们还没有解决这个问题,也没有验证服务器的身份,所以我们必须输入“no”来保护自己不连接到错误的主机。
但是,我们还在“Monkeysphere 警告”部分标题下获得了额外的信息部分。 它告诉我们它能够检索到密钥,但它无法验证服务器,因为它没有必要的信任关系。
如果我们查看客户端计算机密钥链中的密钥,我们会注意到我们现在拥有 SSH 服务器的密钥:
gpg --list-keys
/root/.gnupg/pubring.gpg ------------------------ pub 2048R/87791BD0 2014-03-14 uid client <client@fakedomain.com> sub 2048R/3294D31D 2014-03-14 pub 2048R/54AD641F 2014-03-14 uid admin <admin@fakedomain.com> sub 2048R/A87CADCB 2014-03-14 pub 2048R/0D281337 2014-03-14 uid ssh://fakedomain.com
所以我们现在在我们的系统中有钥匙。 现在我们只需要刷新我们的密钥。 这将为我们系统中的密钥提取任何签名:
gpg --refresh-keys
你应该再次看到一行写着“new signatures: 1
”的行。 我们可以通过检查 SSH 服务器密钥上可用的签名来看到这一点:
gpg --list-sigs ssh:// server.example.com
pub 2048R/0D281337 2014-03-14 uid ssh://server.example.com sig 3 0D281337 2014-03-14 ssh://server.example.com sig 54AD641F 2014-03-14 管理员 @假域名 .com>
如您所见,我们现在看到列出管理员密钥的“sig”行。 由于我们的客户端信任管理员,我们现在可以通过代理信任 SSH 服务器。
让我们再次尝试我们的命令:
ssh -oProxyCommand='monkeysphere ssh-proxycommand %h %p' server.example.com
root@server.example.com's password:
如您所见,我们现在得到了密码提示,而没有要求我们验证 SSH 服务器的有效性。 那是因为我们已经通过GPG验证了它的身份。
为了避免每次我们想通过 SSH 连接到服务器时都必须输入这个长命令,我们将它添加到客户端计算机上的配置文件中:
nano ~/.ssh/config
Host * ProxyCommand monkeysphere ssh-proxycommand %h %p
这将允许我们像往常一样通过 SSH 连接,并将在后台进行所有的 monkeysphere 验证:
ssh server.example.com
要仔细检查这是否有效,请随时删除当前的 known_hosts
文件:
rm ~/.ssh/known_hosts
现在,重试 ssh 命令:
ssh server.example.com
您将登录或提示输入密码,从不询问您是否接受主机。 您还可以看到 known_hosts
文件已自动重新创建并已添加该主机:
cat ~/.ssh/known_hosts
server.example.com ssh-rsa AAAB3NzaC1yc2EAAAADAQABAAABAQC9aTHZmHZSgwNtwichF0AqDI74bCMtI29kqPDZaNn2r86NGIElRUlQiRImmZXs5oEjF0o8VaW6s1cIj0hC5ziDPShJ3VzZTWz9RmJ9xfPPcAPw2JbV1c1Q1bplstQqCZmFcRZyofztnP55HqOiJ4htLMxH+a9lM4AydDZtGHhzU+usxUjHniVbxCUVntpunlwtMk+Mtk9eysVdnJCJyV02/W89HExiO9QRpv+EugKN1eCQYrGvNbKWQKq4gSJ0RDwOSKNgkY/Ii0MsGJ2HuioO9np6IEdeZdgSGHPA23+zZe8asrN62iLUBADDkyIR6FAonCvfh99hbFxpNz2N8Mdb MonkeySphere2014-03-21T21:30:44
结论
如果您将组织配置为使用 monkeysphere 进行 SSH,则 SSH 用户将永远不必质疑组织内主机的合法性。 一旦您的用户信任服务器管理员并将他们的 SSH 配置为依赖于 monkeysphere,并且假设管理员对签署新主机保持警惕,则永远不应要求您的用户验证主机身份。
盲目地接受主机为有效是一个巨大的风险,大多数用户在没有管理员帮助的情况下将无法合法地检查服务器的身份。 因此,使用 Monkeysphere,我们可以为整个组织的安全切断整个过程。
这可能看起来需要做很多工作,但是随着您的进行,建立信任网络的工作将变得越来越少,并且可以让您避免危险的中间人攻击。
在下一篇文章中,我们将讨论 如何使用 monkeysphere 验证您的用户到 SSH 服务器 。