用Yubikeys保护我的个人SSH基础结构

2021-02-09 21:35:27

我在一月份的“现在”帖子中提到的一个最近完成的项目是使用Yubikeys在我的个人计算基础结构中锁定SSH。在这篇文章中,我将概述我的目标,我采取的策略以及在此过程中遇到的问题和解决方案。

从历史上看,我在个人项目中使用了非常基本的SSH设置:每台笔记本电脑/台式机/服务器上的用户帐户在〜/ .ssh中都有自己的密钥,并且我会尝试在所有服务器上保留authorized_keys列表或多或少是最新的。这带来了许多明显的安全问题。

我想确保,如果攻击者获得对我一台服务器的访问权限,则他们将无法使用该访问权限转移到我控制的任何其他计算机上。为此,我转而使用一些Yubikeys来存储我的SSH密钥。不再在任何服务器上存储关键材料,以防假想的攻击者窃取。 Yubikey要求提供PIN,因此这是两因素身份验证的示例:我实际拥有的东西和我知道的东西。

SSH代理转发用于允许我从一台服务器SSH到另一台服务器,或从远程服务器上的GitHub获取代码。

我使用私有Git存储库在计算机之间同步SSH配置(包括authorized_keys),并使用模块化本地配置系统使我能够快速启用仅适用于我的计算机子集的常用SSH配置块。

使用Yubikeys存储SSH密钥需要yubikey-agent。进行设置非常简单;真正的工作是弄清楚如何解决我以后遇到的各种困难。

(此标题下的命令和配置更改适用于带有附加的Yubikey的客户端计算机。)

设置SSH_AUTH_SOCK环境变量(在.bashrc或.zshrc中执行此操作)。在我的dotfile中,我首先检查是否已安装yubikey-agent,然后继续:

通过为〜/ .ssh / config中的主机块添加ForwardAgent yes,为特定的受信任主机启用SSH代理转发(不要为所有主机启用它,这是一个潜在的安全问题)。一个完整的示例可能如下所示:

在本博文后面的内容中,这可能会破坏一些话题,但我们还将其添加到〜/ .ssh / config中:Host * IdentityAgent /usr/local/var/run/yubikey-agent.sock

这允许从终端外部启动的应用程序(例如GUI Git客户端Fork.app)查找并使用yubikey-agent。

我想使用新的macOS应用程序Secretive,该应用程序将SSH密钥存储在较新的MacBooks上的Secure Enclave中,并且需要Touch ID进行身份验证。不幸的是,由于Reasons™,我仍在使用macOS Mojave,Secretive需要Catalina或Big Sur。我计划尽快迁移到Big Sur,因为我想在16英寸型号发布时得到M1 MacBook Pro,所以我将能够尽快尝试Secretive。 (值得注意的是,这会改变安全模型,因为第二个因素是生物特征而非PIN,但仍然是两个因素。)

我将〜/ .ssh目录保存在一个私有Git存储库中,但有几个重要的例外(永不提交键!)。这使我可以轻松地在系统之间同步配置和authorized_keys更改。我在cdzombak / ssh-example中创建了一个简化版本,您可以将其用作自己设置的基础。

authorized_keys是您在Yubikeys上添加与新的专用SSH密钥关联的公共密钥的位置。

在config中,您将为服务器添加主机块。在顶部,它设置了我多年来积累的一些SSH最佳实践。

fix-permissions.sh确保〜/ .ssh / authorized_keys和〜/ .ssh / rc具有正确的权限。我从存储库中拉出后运行它;如果导致任何更改,则应更正存储库中文件的权限。

通过SSH登录到计算机后,rc会运行。在这种情况下,它将更新〜/ .ssh / sock中的符号链接以指向新的SSH代理套接字。有关为什么需要这样做的说明,请参见下面的“长时屏幕会话”部分。

config.templates /包含SSH配置块,可以将其包含在给定的计算机上,但不应在所有地方都包含。其中最重要的是yubikey-agent,启用后将如上所述将IdentityAgent设置为yubikey-agent套接字;还有homedir-ssh-auth-sock,它将SSH登录后将IdentityAgent设置为rc创建的symlink。在任何给定的计算机上,我都启用这两种配置中的一种,并且仅启用其中一种,具体取决于它是连接了Yubikey的客户端计算机还是依赖于代理转发来进行任何SSH连接的服务器。

config.local /被config包含,被Git忽略。我可以从此处将符号链接添加到config.templates中,以在计算机上启用特定的SSH配置块。

最后两个-config.local和config.templates-很重要,因为这就是我在不同机器之间实现SSH配置变化的方式。自述文件介绍了如何在给定计算机上启用配置模板。

我将GNU屏幕用作终端多路复用器,并在SSH会话之间提供了持久性。这是SSH代理转发的问题:当我第一次SSH并启动屏幕会话时,将设置SSH_AUTH_SOCK环境变量。但是,当我从其他地方登录并重新连接到屏幕会话时,SSH_AUTH_SOCK环境变量将不会得到更新,因此在启动新的屏幕会话之前,SSH代理转发已中断。

要点帮助我解决了这种情况。此解决方案有几部分。 (此标题下的命令和配置更改适用于您将通过SSH连接到的服务器。)

首先,我们必须为我们的SSH代理套接字提供一个位置,该位置在两次登录之间不会更改。 〜/ .ssh / rc中的以下几行实现了这一点:

大!然后,我们只需要客户端使用此新的,始终更新的套接字即可。为此,我们配置〜/ .screenrc来设置环境变量SSH_AUTH_SOCK:

最后,我们还希望在我们的SSH配置中包含IdentityAgent〜/ .ssh / sock / ssh_auth_sock。为此,我们可以在模块化SSH配置设置中包含homedir-ssh-auth-sock配置块:

使用sudo运行命令时,您正在新环境中工作;您用户的环境变量不会保留。当然,这将破坏SSH代理转发。

为了解决这个问题,我们想在使用sudo时保留SSH_AUTH_SOCK环境变量。 (此标题下的命令和配置更改适用于您将通过SSH连接到的服务器。)

这意味着,当使用sudo以root用户(而不是任何其他用户)身份运行命令时,SSH_AUTH_SOCK变量保持不变,并且代理转发按预期工作。

Fork应用程序的问题跟踪器中的此问题在这里确实很有帮助。 .bashrc和.zshrc不适用于GUI应用程序(除非您从终端启动它们),因此仅在外壳配置文件中设置SSH_AUTH_SOCK无效。

这就是为什么我们在SSH配置中需要IdentityAgent /usr/local/var/run/yubikey-agent.sock。要在我的模块化SSH配置设置中启用此功能,请执行以下操作:

设置好之后,我的Yubikey会定期闪烁,好像我尝试通过SSH进行连接一样,但是我没有尝试使用SSH做任何事情!这令人担忧,直到我意识到那只是Fork试图在后台更新存储库信息。

我决定在笔记本电脑上将Git配置为在与GitHub和Bitbucket通信时使用HTTPS而不是SSH,因此Fork可以根据需要在后台工作。

为此,我们将以下内容添加到〜/ .gitconfig。 (此更改适用于您希望Git使用HTTPS而不是SSH的任何Mac。)

[url" https://"]代替Of = git:// [url" https://github.com/"]代替Of = [email protected]:[url " https://bitbucket.org/"]代替Of = [email protected]:[凭据] helper = osxkeychain

现在,当您首次尝试对GitHub或Bitbucket存储库执行Git操作时,Git将提示您输入凭据:

对于GitHub,您的密码是具有回购范围的Personal Access Token。对于Bitbucket,您的密码是具有存储库/写入和存储库/读取权限的应用程序密码。

我确实有一个用例,其中一台服务器需要使用SSH上的rsync定期将数据同步到另一台服务器,这意味着不需要物理,实时交互的Yubikey。

为此,接收服务器具有受限制的用户帐户,该帐户仅允许访问必要的数据。启动同步的发送服务器具有SSH密钥,该密钥仅用于此任务;并且只能登录到接收服务器上的受限用户帐户。

为了获得额外的中等安全性(这仍然不是真正的第二要点),接收服务器会使用其authorized_keys文件中的from指令来限制SSH密钥可以登录的IP地址。有关更多详细信息,请参见将SSH登录限制为特定的IP地址和为OpenSSH配置授权密钥。

当笔记本电脑不方便使用时,我偶尔会在iPhone上使用提示2。该应用程序生成自己的SSH密钥,该密钥存储在iPhone中(不在Panic Sync中存储),我将相应的公共密钥添加到SSH配置存储库中的authorized_keys中。

我认为这是相当安全的,因为密钥保留在我的手机上,并且固定在Face ID& iPhone的PIN码,这意味着必须满足两个因素:我拥有的东西和其中之一(生物统计学或我知道的东西)。

Secure ShellFish也有类似的故事。我用它来远程访问家庭NAS上的文件。在这种情况下,Secure ShellFish的SSH密钥实际上仅允许以有限的权限登录到NAS上的用户帐户。它没有添加到我的“核心” SSH配置中。

如果所有其他Yubikey丢失或毁坏,则另外的Yubikey可以住在防火保险箱中,以帮助恢复。 我现在暂时不理会。 我什至只经常使用一台Windows计算机,而无需使用SSH进行任何操作。 很高兴了解支持Yubikeys或Google Titan安全密钥的SSH代理解决方案,但我没有动力自己进行这项工作。