操作指南:OpenSSH 双因素认证(密码和 Google 身份验证器)

来自 Alpine Linux

以下步骤将允许您设置 OpenSSH ssh 服务器以使用双因素身份验证,包括用户密码和基于时间的一次性密码 (TOTP)。

为了实现这一点,您需要添加必需的 APK 包、配置 OpenSSH 服务器、配置 google-authenticator PAM 模块、重启 OpenSSH 服务器,以及为每个用户设置 google-authenticator。


必需的 APK 包

主仓库

社区仓库

文档(可选)

一次性拉取所有 APK 包

# apk add openssh openssh-server-pam google-authenticator openssh-doc google-authenticator-doc

配置 OpenSSH 服务器

注意: 本文假设您已经完成了 OpenSSH 的基本设置,依赖用户名和密码登录... 如果您尚未完成,请参阅文章 设置 SSH 服务器

使用 sudosudoas 将您偏好的文本编辑器提升到 root 权限,然后编辑 /etc/ssh/sshd_config 文件。 如果有以下三个指令不存在,则需要修改或添加

PasswordAuthentication no
AuthenticationMethods keyboard-interactive
UsePAM yes

如果您想使用公钥身份验证,请查阅 sshd_config 手册页,特别是 AuthenticationMethods 指令。


配置 google-authenticator PAM 模块

以 root 身份,创建 /etc/pam.d/sshd 文件并创建一个名为 /etc/pam.d/sshd.pam 的链接

# touch /etc/pam.d/sshd # ln /etc/pam.d/sshd /etc/pam.d/sshd.pam

将您偏好的文本编辑器提升到 root 权限并编辑 /etc/pam.d/sshd 文件,它至少应包含以下行

#%PAM-1.0                                                                                                                                                                                                                                       
auth            required        pam_env.so
auth            required        pam_nologin.so  successok
auth            required        pam_google_authenticator.so       echo_verification_code grace_period=57600 nullok
auth            required        pam_unix.so      sha512
account         include         base-account
password        include         base-password
session         include         base-session

在上面的示例中,我们向 google authenticator PAM 模块传递了一些有用的选项

echo_verification_code 允许用户在输入验证码时看到它,从而减少输入错误的几率。
grace_period=57600 定义一个宽限期(秒),在此期间,来自同一 IP 地址的用户登录尝试将不会被要求输入验证码。
nullok 建议在服务器上 google authenticator 的初始推广过程中使用此选项。 它允许尚未创建密钥的用户绕过验证码提示。 建议在所有用户都创建了密钥后删除此选项。

更多选项可以在 google-authenticator 手册页他们的 github 上找到。

重启 SSH 服务器

为了使上述更改生效,以 root 用户身份运行

# service sshd restart

提示: 如果您远程登录到系统,重启 sshd 不会断开您当前的连接。

这非常有用,因为您可以重启 sshd 并打开一个额外的连接来测试配置更改。 如果您输入错误,可以使用第一个连接进行更正或还原更改,以使 sshd 再次运行。

在继续操作之前,请花时间确保您的 sshd 允许您像往常一样使用用户名/密码登录,而无需 TOTP,并修复任何问题。

为每个用户设置 google-authenticator

指示所有您希望使用一次性密码的用户登录他们的帐户并运行 google-authenticator 命令来设置他们的密钥。

他们将把生成的 OTP 密钥输入到他们的身份验证器应用程序中,并手写他们的 5 个备用代码以存储在安全的位置。

命令输出将如下所示

$ google-authenticator

Do you want authentication tokens to be time-based (y/n) y
Warning: pasting the following URL into your browser exposes the OTP secret to Google:
  A URL APPEARS HERE    
  A URL APPEARS HERE
Failed to use libqrencode to show QR code visually for scanning.
Consider typing the OTP secret into your app manually.
Your new secret key is: 
Ender code from app (-1 to skip):
Your emergency scratch codes are:
  CODE1
  CODE2
  CODE3
  CODE4
  CODE5

Do you want me to update your "/home/$USER/.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, bit it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y

By default, a new token is generated every 30 seconds by the mobile app.
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. This allows for a
time skew of up to 30 seconds between authentication server and client. If you
experience problems with poor time synchronization, you can increase the window
from its default size of 3 permitted codes (one previous code, the current
code, the next code) to 17 permitted codes (the 8 previous codes, the current
code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
between client and server.
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
~$

您需要对前两个问题回答 y

其余问题是个人偏好,我通常回答 y n n,我这样做的理由是

对于 grace_period 选项设置为 60 秒以上的机器,我禁止多次使用身份验证令牌。

我想象不到我处理的任何机器没有启用 NTP(时钟同步),所以我没有启用时间偏差补偿。

我不启用速率限制,因为 sshd 和防火墙应该会处理这个问题。