Google Authenticator
Google Authenticator 提供了一种使用一次性密码 (OTP) 的两步验证程序,该程序最初由 开放身份验证倡议 (OATH) 标准化。该验证机制集成在 Linux PAM 系统中。本指南介绍了该机制的安装和配置。
有关反向操作(在 Linux 下生成与 Google Authenticator 兼容的代码),请参阅下面的 #代码生成。
安装
安装 libpam-google-authenticator 软件包,它提供了客户端程序 google-authenticator(1) 和 PAM 模块 pam_google_authenticator.so。开发版本可通过 google-authenticator-libpam-gitAUR 获取。
配置
本节涵盖了如何配置系统的 PAM,以要求 SSH 验证以及(可选的)桌面登录 使用 Google Authenticator OTP 验证。
SSH
通常人们仅对远程登录要求两步验证。相应的 PAM 配置文件是 /etc/pam.d/sshd。如果您想在全局范围内使用 Google Authenticator,则需要修改 /etc/pam.d/system-auth,但在这种情况下请极其谨慎,以免将自己锁定在系统之外。在本指南中,我们通过编辑 /etc/pam.d/sshd 来进行,这在本地会话中操作是最安全的(但并非必须)。
若要同时输入 Unix 密码和 OTP,请将 pam_google_authenticator.so 添加到 /etc/pam.d/sshd 中 system-remote-login 行之上。
auth required pam_google_authenticator.so auth include system-remote-login account include system-remote-login password include system-remote-login session include system-remote-login
这将在提示输入 Unix 密码之前先要求输入 OTP。更改这两个模块的顺序将反转此顺序。
若要允许使用 OTP 或 Unix 密码其中之一登录,请使用:
auth sufficient pam_google_authenticator.so
在 /etc/ssh/sshd_config.d/99-archlinux.conf 中启用键盘交互认证 (keyboard interactive authentication)。
KbdInteractiveAuthentication yes
最后,重新加载 sshd.service。
AuthenticationMethods 以同时允许:双因子验证和基于密钥的验证。请参阅 OpenSSH#Two-factor authentication and public keys。仅在从本地网络外部连接时请求 OTP
有时,我们只想在从本地网络外部连接时启用 2FA 功能。为了实现这一点,请创建一个文件(例如 /etc/security/access-local.conf)并添加允许绕过 2FA 的网络地址
# only allow from local IP range + : ALL : 192.168.20.0/24 # Additional network: VPN tunnel ip range (in case you have one) + : ALL : 10.8.0.0/24 + : ALL : LOCAL - : ALL : ALL
然后编辑您的 /etc/pam.d/sshd 并添加以下行:
#%PAM-1.0 auth [success=1 default=ignore] pam_access.so accessfile=/etc/security/access-local.conf auth required pam_google_authenticator.so auth include system-remote-login account include system-remote-login password include system-remote-login session include system-remote-login
success=1 仅在 pam_google_authenticator 行之后至少存在另一行认证行时才有效。如果不是这种情况,success 必须设置为 done。桌面登录
Google Authenticator PAM 插件也可用于控制台登录和 GDM。只需将以下内容添加到 /etc/pam.d/login 或 /etc/pam.d/gdm-password 文件中:
auth required pam_google_authenticator.so
用法
每个想要使用两步验证的用户都需要:
- 在其主文件夹中生成一个密钥文件,并且
- 相应地设置其 OTP 生成器
生成密钥文件
google-authenticator 按照以下方式生成 TOTP 密钥文件:
$ google-authenticator
Do you want authentication tokens to be time-based (y/n) y generated_QR_code_here Your new secret key is: ZVZG5UZU4D7MY4DH Your verification code is 269371 Your emergency scratch codes are: 70058954 97277505 99684896 56514332 82717798 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 is not 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
建议安全地保存紧急备份代码 (emergency scratch codes)(将其打印并保存在安全位置),因为当您丢失手机(即 OTP 生成器)时,这是您登录(通过 SSH)的唯一方式。它们也存储在 ~/.google_authenticator 中,因此只要您处于登录状态,随时都可以查看它们。
存储位置
如果您想更改密钥文件的存储路径,可以使用 --secret 标志
$ google-authenticator --secret="/path_folder/username"
然后,不要忘记在 /etc/pam.d/sshd 中更改 PAM 的位置路径
/etc/pam.d/sshd
auth required pam_google_authenticator.so user=root secret=/path_folder/${USER}
user=root 用于强制 PAM 使用 root 用户搜索文件。
此外,请注意密钥文件的权限。该文件必须仅对所有者可读 (chmod: 400)。在这里,所有者是 root。
$ chown root:root /path_file/secret_key_files $ chmod 400 /path_file/secret_key_files
代码生成
在最后的设置步骤中,每个用户必须将其主目录中生成的密钥文件与所选的 OTP 生成器关联,以提供验证码。用户可以在不同设备上设置生成器以实现冗余,例如在手机上的 OTP 应用程序和一个独立的密码管理器中,或者决定依赖于之前生成的紧急备份代码作为备份。
手机生成器
在您的手机上安装一个生成器应用程序(例如):
- FreeOTP (Android 版 F-Droid, Google Play;iOS 版 App Store)。
- FreeOTP+ (Android 版 F-Droid, Google Play)。
- Aegis (Android 版 F-Droid, Google Play)。
- Bitwarden (Android 版 F-Droid, Google Play;iOS 版 App Store)。
- Google Authenticator (Android 版 Google Play;iOS 版 App Store)。
在移动应用程序中,创建一个新账户,然后扫描生成密钥文件时告知您的 URL 中的 QR 码,或者手动输入密钥(在上述示例中为 'ZVZG5UZU4D7MY4DH')。
现在,您应该看到手机上每 30 秒生成一个新的验证码令牌。
如果您将 Google Authenticator 配置在其他系统中,那么丢失设备可能会导致您无法登录这些系统。拥有额外的代码生成方式会非常有帮助。
代码管理器
gashellAUR 提供了一个支持显示、生成、存储和管理 Google Authenticator 代码的脚本。另一个可选方案是 auther-gitAUR。
KeePassXC
GUI 密码管理器 keepassxc 允许将其条目与 Google Authenticator 代码关联,然后它可以生成 OTP 代码并通过 QR 码导出其密钥。
命令行
生成代码最简单的方法是使用 oathtool(1)。它包含在 oath-toolkit 软件包中,可以使用如下方式:
$ oathtool --totp --base32 secret_key
在大多数具有足够用户权限的 Android 系统上,由于 Google Authenticator 数据库是一个 sqlite3 数据库,因此可以将其从设备中复制出来并直接访问。然而,在 2022 年 7 月的某个时间点,账户表中的密钥列开始使用加密。如果您的数据库备份没有使用这种加密,此 shell 脚本将读取 Google Authenticator 数据库并为找到的每个密钥生成实时代码
google-authenticator.sh
#!/bin/sh
# This is the path to the Google Authenticator app file. It is typically
# located in /data under Android. Copy it to your PC in a safe location and
# specify the path to it here.
DB="/path/to/com.google.android.apps.authenticator/databases/databases"
sqlite3 "$DB" 'SELECT email,secret FROM accounts;' | while read A
do
NAME=`echo "$A" | cut -d '|' -f 1`
KEY=`echo "$A" | cut -d '|' -f 2`
CODE=`oathtool --totp -b "$KEY"`
echo -e "\e[1;32m$CODE\e[0m - \e[1;33m$NAME\e[0m"
done
测试
从另一台机器和/或另一个终端窗口 SSH 连接到您的主机
$ ssh hostname login as: username Verification code: generated/backup_code Password: password $