Google Authenticator

来自 ArchWiki

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 身份验证,以及(可选)桌面登录

注意: 完整配置需要生成密钥文件。 建议在编辑(并因此应用)PAM 配置之前生成它。

SSH

警告: 如果您通过 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。 更改两个模块的顺序将颠倒此顺序。

警告: 只有生成了密钥文件的用户(见下文)才允许使用 SSH 登录。

要允许使用 OTP 或您的 Unix 密码登录,请使用

auth            sufficient      pam_google_authenticator.so

/etc/ssh/sshd_config.d/99-archlinux.conf 中启用键盘交互式身份验证

KbdInteractiveAuthentication yes

最后,重新加载 sshd.service

警告: 如果您使用 SSH 密钥对进行身份验证并且已禁用密码登录,则 OpenSSH 将忽略所有这些设置。 但是,从 OpenSSH 6.2 开始,您可以添加 AuthenticationMethods 以同时允许两种身份验证方式:双因素身份验证和基于密钥的身份验证。 请参阅 OpenSSH#双因素身份验证和公钥

仅当从本地网络外部连接时请求 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

桌面登录

警告: 在另一个控制台上测试结果之前,请勿注销会话。

Google Authenticator PAM 插件也可用于控制台登录和 GDM。 只需将以下内容添加到 /etc/pam.d/login/etc/pam.d/gdm-password 文件中

auth required pam_google_authenticator.so

使用

每个想要使用两步验证的用户都需要

  • 在其主文件夹中生成一个密钥文件,以及
  • 相应地设置他们的 OTP 生成器

生成密钥文件

提示: 安装 qrencode 以生成可扫描的二维码。 使用身份验证器应用程序扫描二维码以自动配置密钥。

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

建议安全地存储紧急备用代码(将它们打印出来并保存在安全的位置),因为当您丢失手机(即您的 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 应用程序和单独的密码管理器中,或者决定依赖先前生成的紧急备用代码作为备份。

手机生成器

在您的手机上安装生成器应用程序(例如)

在移动应用程序中,创建一个新账户,然后扫描在生成密钥文件时告诉您的 URL 中的二维码,或者手动输入密钥(在上面的示例中为“ZVZG5UZU4D7MY4DH”)。

现在您应该看到手机上每 30 秒生成一个新的密码令牌。

如果您已将 Google Authenticator 配置为与其他系统一起使用,那么丢失您的设备可能会使您无法登录这些系统。 拥有其他生成代码的方式可能会有所帮助。

代码管理器

脚本 gashellAUR 提供了显示、生成、存储和管理 Google Authenticator 代码的功能。 另一种选择是 auther-gitAUR

KeePassXC

GUI 密码管理器 keepassxc 允许将 Google Authenticator 代码与其条目关联,然后它可以生成 OTP 代码并通过二维码导出其密钥。

命令行

生成代码的最简单方法是使用 oathtool(1)。 它在 oath-toolkit 软件包中提供,可以按如下方式使用

$ oathtool --totp --base32 secret_key

在大多数具有足够用户访问权限的 Android 系统上,可以复制设备上的 Google Authenticator 数据库并直接访问,因为它是一个 sqlite3 数据库。 但是,在 2022 年 7 月的某个时候,accounts 表上的 secret 列开始使用加密。 如果您的数据库备份未使用此加密,则此 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
$