双因素认证优于单因素认证
虽然我一直对安全感兴趣,但总有一些安全措施是我不喜欢的。SSH 暴力破解攻击最终成为攻击者入侵 Linux 系统的主要方式,但当涉及到保护 SSH 时,我从来都不喜欢将 SSH 端口更改为隐蔽的端口,也不喜欢像 fail2ban 这样的脚本,它们试图检测暴力破解攻击并使用防火墙规则阻止攻击者。对我来说,这些措施回避了真正的问题:暴力破解攻击需要密码认证。如果您禁用密码认证(在您的 sshd_config 中将 PasswordAuthentication
设置为 no)并且仅使用 SSH 密钥,您就可以对所有那些敲门的暴力破解攻击感到放心了。
在过去的一篇文章(“秘密特工”,2013 年 12 月)中,我写了为什么您应该为您的 SSH 密钥设置密码,以及如何使用 SSH Agent 使受密码保护的密钥不那么烦人。在某种程度上,您可以将受密码保护的 SSH 密钥视为一种双因素认证形式。密钥是您拥有的东西,密码是您知道的东西。然而,问题是,如果您托管一个拥有多个用户的系统,您无法从服务器端强制执行受密码保护的 SSH 密钥。因此,在本文中,我将讨论如何为仅接受密钥的 SSH 服务器添加双因素认证。
如今,越来越多的在线服务提供双因素认证 (2FA) 作为用户名和密码之上的额外安全层。在您执行正常的身份验证后,您需要提供您的 2FA 令牌(通常是一串数字)来验证您的身份。虽然在过去,2FA 需要您随身携带一个特殊的硬件密钥,但如今,许多软件方法可以使用您的手机来代替。一些方法使用 TOTP(基于时间的一次性密码),因此您的手机只需要准确的时间,而不需要网络即可运行。其他方法使用推送通知、短信甚至电话呼叫来共享 2FA 令牌,并且某些实现可以使用以上所有方法。
一些 2FA SSH 实现通过放置在特定用户的 SSH 配置中的 ForceCommand
指令工作,并允许您在每个用户的基础上启用 2FA。其他一些实现提供了一个 PAM 模块,您可以系统范围地添加该模块(并用于 sudo 身份验证以及 SSH)。尽管 Linux 上存在许多出色的 2FA SSH 实现,但我选择了 Google Authenticator,原因如下:
-
它是免费的,并且源代码是可用的。
-
它已经可用并经过多年的测试。
-
软件包适用于许多发行版。
-
客户端适用于许多手机操作系统。
-
它使用自定义 PAM 模块,因此很容易系统范围地添加 2FA。
-
它以备份代码的形式提供备份,以防用户丢失或擦除他们的手机。
正如我所提到的,Google Authenticator 针对许多发行版进行了打包,因此,例如,在基于 Debian 的系统上,您可以使用以下命令安装它:
$ sudo apt-get install libpam-google-authenticator
如果由于某种原因它没有针对您的发行版打包,您也可以直接访问 这里,下载该软件,并根据那里的文档进行 make 和安装。您还需要在您的手机上安装 Google Authenticator 应用程序。
配置用户帐户我建议在 SSH 中强制执行 2FA 之前,为您的所有用户帐户(或至少所有系统管理员帐户)设置 Google Authenticator,以便更轻松地注册所有用户并避免将人们拒之门外的风险。要配置 Google Authenticator,每个用户需要登录并运行 google-authenticator。您将被问到一系列问题,回答“y”是安全的;但是,我通常对将时间窗口延长到四分钟回答“否”,并且我也对速率限制回答“否”,因为当我禁用密码认证时,我不太担心暴力破解攻击。输出看起来像这样:
$ google-authenticator
Do you want authentication tokens to be time-based (y/n) y
https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl
↪=otpauth://totp/username@debian%3Fsecret%3D4SK2LTLCTLCEV757
QR Code Removed
Your new secret key is: 4SK2LTLCTLCEV757
Your verification code is 221544
Your emergency scratch codes are:
53267360
44975412
59302752
36003899
64736155
Do you want me to update your "/home/username/.google_authenticator"
↪file (y/n) y
Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it
increases your chances to notice or even prevent man-in-the-middle
attacks (y/n) y
By default, tokens are good for 30 seconds and in order to
compensate for possible time-skew between the client and the
server, we allow an extra token before and after the current time.
If you experience problems with poor time synchronization, you can
increase the window from its default size of 1:30min to about 4min.
Do you want to do so (y/n) n
If the computer that you are logging into isn't hardened against
brute-force login attempts, you can enable rate-limiting for the
authentication module. By default, this limits attackers to no
more than 3 login attempts every 30s. Do you want to enable
rate-limiting (y/n) n
如果您安装了 libqrencode,输出还将包含控制台中的 QR 码,您可以使用手机上的 Google Authenticator 应用程序扫描该 QR 码。否则,您只需将密钥输入到手机上的 Google Authenticator 应用程序中即可。另外,请务必写下这些备份代码并将它们存储在安全的地方。这些是一次性使用的代码,您可以使用它们在您丢失或擦除手机的情况下重新进入系统。一旦您重新登录,您可以再次运行 google-authenticator。
配置 PAM 和 SSH一旦您的手机和用户帐户配置了 Google Authenticator,您就可以在 PAM 和 SSH 中强制执行 2FA 了。为此,编辑您的 /etc/pam.d/sshd 文件,并将以下内容添加到文件顶部:
auth required pam_google_authenticator.so
在我的 Debian 系统上,我注意到一旦我完成配置过程,我不仅会被提示输入我的 2FA 令牌,还会被提示输入我的本地系统密码。因为我对三因素认证(二点五因素认证?)不感兴趣,所以我注意到我需要注释掉文件中更靠下的以下内容:
@include common-auth
当然,如果您不是在基于 Debian 的系统上,则可能不需要这个额外的步骤。
最后一步是配置 SSH。希望您过去已经为 SSH 禁用了密码认证,如果还没有,我建议您考虑一下。大多数 SSH 2FA 指南(包括这篇)都会告诉您在您的 /etc/ssh/sshd_config 中启用 ChallengeResponseAuthentication
:
ChallengeResponseAuthentication yes
但是,我注意到,当您使用基于密钥的身份验证而不是密码时,您需要在配置文件中添加一个额外的设置:
AuthenticationMethods publickey,keyboard-interactive
一旦这些设置到位,您可以通过重启您的 SSH 服务来启用它们,根据您的系统,重启命令可能是以下之一:
$ sudo service ssh restart
$ sudo service sshd restart
在 SSH 重启后,您下次 SSH 连接到服务器时应该会收到一个额外的提示:
$ ssh kyle@server1.example.com
Authenticated with partial success.
Verification code:
输入在您的 Google Authenticator 手机应用程序中显示的验证码,您就可以登录了。为 SSH 添加 2FA 的好处是,它在您的计算机被入侵或被盗的情况下提供了额外的保护手段。攻击者还必须入侵或盗取您的手机才能访问您的系统。