如何在CentOS 7上为SSH设置多重身份验证

本文将介绍如何使用OATH-TOTP应用程序以及SSH密钥启用SSH身份验证。然后通过SSH登录到您的服务器将需要两个通道的两个因素,从而使它比单独的密码或SSH密钥更安全。

介绍

身份验证因素是用于证明您有权执行操作(例如登录系统)的单一信息。 认证通道是认证系统向用户递送因素或要求用户回复的方式。密码和安全令牌是认证因素的示例;电脑和手机是频道的例子。 默认情况下,SSH使用密码进行身份验证,大多数SSH强化指示建议使用SSH密钥。然而,这仍然只是一个因素。如果一个坏的演员已经危害您的计算机,那么他们可以使用您的密钥来危害您的服务器以及。 在本教程中,我们将设置多因素身份验证来应对。多重身份验证 (MFA)需要多个因素才能进行身份验证或登录。这意味着不良演员将不得不妥协多项内容,例如您的计算机和手机,进入。不同类型的因素通常总结为:
  1. 知道的一些东西 ,比如密码或安全问题
  2. 有的东西 ,像验证器应用程序或安全令牌
  3. 是什么 ,像你的指纹或声音
一个常见的因素是OATH-TOTP应用程序,如Google Authenticator。OATH-TOTP (开放认证基于时间的一次性密码)是一种开放协议,它生成一次性使用密码,通常为每30秒循环使用的6位数字。 本文将介绍如何使用OATH-TOTP应用程序以及SSH密钥启用SSH身份验证。然后通过SSH登录您的服务器将需要两个通道的两个因素,从而使它比单独的密码或SSH密钥更安全。此外,我们将讨论一些额外的用例MFA和一些有用的提示和技巧。

先决条件

要遵循本教程,您需要:

第1步 - 安装Google的PAM

在此步骤中,我们将安装和配置Google的PAM。 PAM代表可插入认证模块 ,是在Linux系统上用于认证用户的认证基础结构。 由于Google制作了OATH-TOTP应用程序,他们还制作了一个PAM来生成TOTP,并且与任何OATH-TOTP应用程序(如Google Authenticator或Authy)完全兼容 。 首先,我们需要添加EPEL(企业Linux的额外软件包)repo。
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
接下来,安装PAM。如果这是第一次使用repo,可能会提示您接受EPEL密钥。一旦接受,您将不会再被提示接受密钥。
sudo yum install google-authenticator
安装PAM后,我们将使用PAM附带的帮助程序应用程序为要添加第二个因素的用户生成TOTP密钥。此密钥是在逐个用户的基础上生成的,而不是系统范围的。这意味着每个想要使用TOTP身份验证应用程序的用户都需要登录并运行帮助应用程序来获取自己的密钥;你不能只是运行一次为每个人启用它(但在本教程结尾处有一些提示,为许多用户设置或要求MFA)。 运行初始化应用程序。
google-authenticator
运行命令后,系统会询问您几个问题。第一个询问认证令牌是否应该是基于时间的。
Do you want authentication tokens to be time-based (y/n) y
此PAM允许基于时间或基于顺序的令牌。使用基于顺序的令牌意味着代码在某一点开始,然后在每次使用后增加代码。 使用基于时间的令牌意味着代码在一定时间过去之后随机改变。我们会坚持基于时间,因为这是谷歌Authenticator预期的应用程序,所以回答是。 回答这个问题后,很多输出将滚动过去,包括一个大的QR码。此时,在手机上使用您的验证器应用程序扫描QR码或手动键入密钥。如果QR码太大而无法扫描,您可以使用QR码上方的网址获取更小的版本。添加完成后,您会在应用中看到一个六位数的代码,每30秒更改一次。 注意 :请确保将密钥,验证码和恢复码记录在安全的位置,例如密码管理器。恢复代码是恢复访问权限的唯一方法,例如,如果您无法访问您的TOTP应用。 剩下的问题告诉PAM如何运作。我们将逐一介绍它们。
Do you want me to update your "/home/sammy/.google_authenticator" file (y/n) y
这会将键和选项写入.google_authenticator文件。如果你说不,程序退出,没有写,这意味着验证器将不工作。
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. 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 +-1min (window size of 3) to about +-4min (window size of 17 acceptable tokens). 
Do you want to do so? (y/n) n
回答是这里允许在一个移动的四分钟窗口最多8个有效的代码。通过回答否,您在1:30分钟滚动窗口中将其限制为3个有效代码。除非你发现1:30分钟的问题,回答否是更安全的选择。
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) y
速率限制意味着远程攻击者只能在被阻止之前尝试一定数量的猜测。如果以前没有配置速率限制直接到SSH,现在这样做是一个伟大的加固技术。 注意 :完成此设置后,如果要备份密钥,您可以将~/.google-authenticator文件复制到受信任的位置。从那里,您可以将其部署在其他系统上,或在备份后重新部署。 现在,Google的PAM已安装并配置,下一步是配置SSH以使用您的TOTP密钥。我们需要告诉SSH关于PAM,然后配置SSH使用它。

第2步 - 配置OpenSSH

因为我们将通过SSH进行SSH更改,所以重要的是不要关闭您的初始SSH连接。相反,打开第二个SSH会话进行测试。这是为了避免锁定自己的服务器,如果你的SSH配置有一个错误。一旦一切正常,您就可以安全地关闭任何会话。 开始我们将编辑sshd配置文件。 在这里,我们使用nano ,默认情况下不安装在CentOS上。 您可以使用sudo yum install nano安装它,或使用您喜欢的替代文本编辑器。
sudo nano /etc/pam.d/sshd
将以下行添加到文件的底部。
/etc/pam.d/sshd
. . .
# Used with polkit to reauthorize users in remote sessions
-session   optional     pam_reauthorize.so prepare
auth required pam_google_authenticator.so nullok
最后一行末尾的nullok字告诉PAM该认证方法是可选的。 这允许没有OATH-TOTP令牌的用户仍然使用他们的SSH密钥登录。 一旦所有用户都有OATH-TOTP令牌,您可以从此行中删除nullok ,以使MFA成为强制性。 保存并关闭文件。 接下来,我们将配置SSH以支持此类身份验证。打开SSH配置文件进行编辑。
sudo nano /etc/ssh/sshd_config
查找ChallengeResponseAuthentication行。 注释掉no行,取消注释no行。
/ etc / ssh / sshd_config
. . .
# Change to no to disable s/key passwords
ChallengeResponseAuthentication yes
#ChallengeResponseAuthentication no
. . .
保存并关闭文件,然后重新启动SSH以重新加载配置文件。重新启动sshd服务不会关闭打开的连接,所以你不会冒险用这个命令自己锁定。
sudo systemctl restart sshd.service
要测试一切工作到目前为止,打开另一个终端,并尝试通过SSH登录。如果您之前已创建SSH密钥并正在使用SSH密钥,则会注意到您无需键入用户密码或MFA验证码。这是因为SSH密钥默认覆盖所有其他身份验证选项。否则,您应该得到密码和验证码提示。 如果你想确保你迄今为止做的工作,在你打开的SSH会话导航到~/.ssh/ ,并重命名authorized_keys文件,暂时,并打开一个新的会话,并使用我们的密码和验证码。
cd ~/.ssh
mv authorized_keys authorized_keys.bak
一旦您验证了您的TOTP令牌工作,将“authorized_keys.bak”文件重命名为它的名称。
mv authorized_keys.bak authorized_keys
接下来,我们需要启用SSH密钥作为一个因素,验证码作为第二个因素,告诉SSH哪些因素要使用,并防止SSH密钥覆盖所有其他类型。

第3步 - 使SSH意识到MFA

重新打开sshd配置文件。
sudo nano /etc/ssh/sshd_config
在文件底部添加以下行。这告诉SSH需要哪些验证方法。这一行告诉SSH我们需要一个SSH密钥和一个密码或一个验证码(或所有三个)。
/ etc / ssh / sshd_config
. . .
# Added by DigitalOcean build process
ClientAliveInterval 120
ClientAliveCountMax 2
AuthenticationMethods publickey,password publickey,keyboard-interactive
保存并关闭文件。 接下来,再次打开PAM sshd配置文件。
sudo nano /etc/pam.d/sshd
找到行auth substack password-auth到文件的顶部。 通过在行上添加一个#字符作为第一个字符进行注释。这告诉PAM不要提示输入密码。
/etc/pam.d/sshd
. . .
#auth       substack     password-auth
. . .
保存并关闭文件,然后重新启动SSH。
sudo systemctl restart sshd.service
现在尝试使用不同的会话再次登录服务器。与上次不同,SSH应该要求您提供验证码。输入后,您将登录。即使您没有看到任何迹象表明您的SSH密钥已被使用,您的登录尝试使用两个因素。如果要验证,可以在SSH命令后添加-v (用于verbose):
. . .
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /Users/sammy/.ssh/id_rsa
debug1: Server accepts key: pkalg ssh-rsa blen 279
Authenticated with partial success.
debug1: Authentications that can continue: keyboard-interactive
debug1: Next authentication method: keyboard-interactive
Verification code:
在输出结束时,您将看到SSH使用您的SSH密钥,然后请求验证码。您现在可以使用SSH密钥和一次性密码通过SSH登录。如果要强制实施所有三种认证类型,可以按照下一步操作。

第4步 - 添加第三个因子(可选)

在第3步中,我们在sshd_config文件中列出了已批准的身份验证类型:
  1. publickey (SSH密钥)
  2. password publickey (密码)
  3. keyboard-interactive (验证码)
虽然我们列出了三个不同的因素,我们目前选择的选项,他们只允许SSH密钥和验证码。如果您想要拥有所有三个因素(SSH密钥,密码和验证码),一个快速更改将启用这三个因素。 打开PAM sshd配置文件。
sudo nano /etc/pam.d/sshd
找到先前注释掉的行, # #auth substack password-auth ,并通过删除#字符取消注释行。保存并关闭文件。现在再次,重新启动SSH。
sudo systemctl restart sshd.service
通过启用选项auth substack password-auth ,PAM现在将提示输入密码以及检查SSH密钥并请求我们以前工作的验证码。现在我们可以使用我们知道的东西(密码)和两种不同类型的东西(SSH密钥和验证码)。 到目前为止,本文概述了如何使用SSH密钥和基于时间的一次性密码启用MFA。如果这是所有你需要,你可以在这里结束。然而,这不是进行多因素认证的唯一方法。以下是使用此PAM模块进行多因素身份验证的几种额外方法,以及一些用于恢复,自动使用等的提示和技巧。

提示1 - 恢复访问

与任何加固和安全的系统一样,您负责管理该安全性。在这种情况下,这意味着不会丢失您的SSH密钥或您的TOTP密钥,并确保您有权访问您的TOTP应用程序。但是,有时会发生事情,您可能无法控制您需要进入的键或应用程序。

丢失SSH密钥或TOTP密钥

如果您丢失SSH密钥或TOTP密钥,恢复可以分成几个步骤。第一个是在不知道验证码的情况下恢复,第二个是找到密钥或重新生成它用于正常的MFA登录。 要在丢失在DigitalOcean Droplet上生成验证码的密钥之后进入,您只需使用仪表板中的虚拟控制台 ,使用您的用户名和密码登录即可。 否则,您将需要具有sudo访问权限的管理用户;请确保不为此用户启用MFA,但只使用SSH密钥。如果您或其他用户丢失其密钥,并且无法登录,则管理用户可以登录,并帮助为使用sudo的任何用户恢复或重新生成密钥。 一旦您登录,有两种方法来帮助获得TOTP密码:
  1. 恢复现有密钥
  2. 生成新密钥
在每个用户的主目录中,密钥和Google身份验证器设置都保存在~/.google-authenticator 。 这个文件的第一行是一个密钥。 快速获取密钥的方法是执行以下命令,显示google-authenticator文件的第一行(即密钥)。然后,获取该密钥,并手动将其键入TOTP应用程序。
head -n 1 /home/sammy/.google_authenticator
如果有理由不使用现有密钥(例如,无法轻易地与受影响的用户安全地共享密钥或现有密钥已泄漏),则可以直接删除~/.google-authenticator文件。 这将允许用户仅使用一个因素再次登录,假设您没有通过删除'/etc/pam.d/sshd'文件中的'nullok'来实施MFA。 然后,他们可以运行google-authenticator来生成新密钥。

无法访问TOTP应用程序

如果您需要登录到服务器,但无法访问TOTP应用以获取验证码,则仍然可以使用第一次创建密钥时显示的恢复代码登录。请注意,这些恢复代码是一次性使用。一旦用于登录,它不能再用作验证码。

提示2 - 更改身份验证设置

如果要在初始配置后更改MFA设置,而不是使用更新的设置生成新配置,则只需编辑~/.google-authenticator文件即可。此文件按以下方式布局:
.google-authenticator布局
<secret key>
<options>
<recovery codes>
在此文件中设置的选项在选项部分中有一行;如果在初始设置期间对特定选项回答“否”,则相应的行将从文件中排除。 以下是您可以对此文件所做的更改:
  • 要启用顺序代码而不是基于时间的代码,请将" TOTP_AUTH " HOTP_COUNTER 1行更改为" HOTP_COUNTER 1
  • 要允许单个代码的多次使用,请删除行" DISALLOW_REUSE
  • 要将代码到期时间窗口延长到4分钟,请添加行" WINDOW_SIZE 17
  • 要禁用多个失败的登录(速率限制),请删除行" RATE_LIMIT 3 30
  • 要更改速率限制的阈值,找到" RATE_LIMIT 3 30行并调整数字。原始值中的3表示一段时间内的尝试次数, 30表示以秒为单位的时间段。
  • 要禁用恢复代码的使用,请删除文件底部的五个8位代码。

提示3 - 避免某些帐户的MFA

可能存在单个用户或少数服务帐户(即,由应用程序使用的帐户,而不是人)在不启用MFA的情况下需要SSH访问的情况。例如,某些使用SSH的应用程序(如某些FTP客户端)可能不支持MFA。如果应用程序没有办法请求验证码,则该请求可能会卡住,直到SSH连接超时。 只要/etc/pam.d/sshd设置/etc/pam.d/sshd中的几个选项,就可以控制在逐个用户的基础上使用哪些因素。 要为某些帐户允许MFA并为其他帐户允许SSH密钥,请确保/etc/pam.d/sshd中的以下设置处于活动状态。
/etc/pam.d/sshd
#%PAM-1.0
auth       required     pam_sepermit.so
#auth       substack     password-auth

. . .

# Used with polkit to reauthorize users in remote sessions
-session   optional     pam_reauthorize.so prepare
auth       required      pam_google_authenticator.so nullok
在这里, auth substack password-auth被注释掉,因为密码需要被禁用。 如果一些帐户意味着禁用MFA,则不能强制MFA,因此在最后一行留下nullok选项。 设置此配置后,只需对任何需要MFA的用户运行google-authenticator ,并且不要为仅使用SSH密钥的用户运行google-authenticator

提示4 - 使用配置管理自动进行设置

许多系统管理员使用配置管理工具 ,如Puppet,Chef或Ansible来管理他们的系统。如果要使用这样的系统安装,在创建新用户的帐户时设置密钥,有一种方法。 google-authenticator支持命令行开关,以在单个非交互式命令中设置所有选项。 要查看所有选项,您可以键入google-authenticator --help 。下面是将设置一切如第1步中概述的命令:
google-authenticator -t -d -f -r 3 -R 30 -W
这将回答我们手动回答的所有问题,将其保存到文件,然后输出密钥,QR码和恢复代码。 (如果添加标志-q ,则不会有任何输出。)如果您以自动方式使用此命令,请确保捕获密钥和/或恢复代码,并将其提供给用户。

提示5 - 强制所有用户的MFA

如果你想强制MFA为所有用户,即使在第一次登录,或者如果你不想依靠你的用户生成自己的密钥,有一个简单的方法来处理这个。您可以为每个用户使用相同的.google-authenticator文件,因为文件中没有存储用户特定的数据。 为此,在初始创建配置文件后,特权用户需要将文件复制到每个主目录的根目录,并将其权限更改为适当的用户。您还可以将文件复制到/etc/skel /,以便在创建时自动复制到新用户的主目录。 警告 :这可能是一个安全风险,因为每个人都共享相同的第二个因素。这意味着如果它泄漏,就好像每个用户只有一个因素。如果你想使用这种方法,考虑这一点。 强制创建用户密钥的另一种方法是使用bash脚本:
  1. 创建TOTP令牌,
  2. 提示他们下载Google Authenticator应用,并扫描将显示的QR码
  3. 在检查.google-authenticator文件是否已存在后,为它们运行google-authenticator程序。
要确保脚本在用户登录时运行,可以将其命名为.bash_login ,并将其放在其主目录的根目录下。

结论

也就是说,通过两个渠道(你的电脑+你的手机)有两个因素(一个SSH密钥+ MFA令牌),你使外部代理很难通过SSH强行进入你的机器,并大大增加您的机器的安全。