为 Linux 用户登录添加谷歌二次验证器保护

为 Linux 用户登录添加谷歌二次验证器保护

Google Authenticator 使用一次性密码(One-time Passcodes)(OTP)进行两步验证。iOS、Android 和 Blackberry 上都提供了 OTP 生成器应用。两步验证的机制集成在Linux的 PAM 系统中。

安装软件包

使用包管理器安装 libpam-google-authenticator 软件包,或从这里下载源码自行编译。
我使用pacman包安装软件包:sudo pacman -S libpam-google-authenticator
如果你用过Google Authenticator二次验证器的话你肯定知道,添加密钥的方式有两种:一种是扫描二维码添加密钥,另外一种是手动输入密钥。
若要扫码添加,则需要在终端生成配置二维码,你需要额外安装 qrencode 软件包。不想扫码的话你可以不用安装,这个软件包是一个可选项。

设置插入式验证模块

注意⚠️:若通过 SSH 进行 Google Authenticator 的所有配置,在完成所有配置并测试正常之前,请勿关闭 SSH 会话,否则可能会无法登录。此外,最好在激活 PAM 之前生成密钥文件,关于密钥文件在下方会有介绍。

通常情况下你仅仅需要在远程 SSH 登陆的时候才需要开启二次验证,对应的PAM的配置在文件 /etc/pam.d/sshd ,你可以使用vim或你熟悉的文本编辑器在非注释行的行首添加:
auth required pam_google_authenticator.so

sudoedit /etc/pam.d/sshd 编辑后的内容如下

/etc/pam.d/sshd
1
2
3
4
5
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

这样将会首先询问二次验证码,验证成功后才会询问密码,二者都要成功验证后才允许登录。
交换 pam_google_authenticator.sosystem-remote-login 两行会改变验证顺序。

若要二者任一正确即可登陆的话则,将配置信息修改为 auth sufficient pam_google_authenticator.so。此时会先询问二次验证码,若正确则直接登录到系统,否则验证密码,两者任一正确即可登录系统。

还需要在文件/etc/ssh/sshd_config内开启质疑-应答认证:
修改配置项为:ChallengeResponseAuthentication yes
并重载sshd服务:systemctl reload sshd

注意⚠️:如果当前你设置使用密钥登陆并禁止密码登录, OpenSSH 会忽略如上所有的配置,若想使用密钥登陆同时开启二次验证的话你需要几个额外步骤:
添加或修改/etc/ssh/sshd_config配置文件 :

  • 配置项 KbdInteractiveAuthentication yes
  • 配置项 ChallengeResponseAuthentication yes
  • 配置项 AuthenticationMethods publickey,keyboard-interactive:pam

默认的 PAM 认证规则中包含密码认证,既然只用密钥和二次验证码登陆系统,则需要修改 sshd 的 PAM 规则,编辑/etc/pam.d/sshd文件,关闭密码验证:

/etc/pam.d/sshd
1
2
3
4
5
6
7
#%PAM-1.0
#auth required pam_securetty.so #disable remote root
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

在修改完如上配置后需要重载sshd服务,sudo systemctl reload sshd
放心,我们目前为止所有的操作和添加的规则仅针对 SSH 远程登录有效,到目前位置还没有结束,你还需要最后一步,为用户生成密钥。

生成密钥文件

提示✅:可选安装 qrencode 软件包以在屏幕上生成可以扫描的二维码。扫描二维码以自动配置两次验证器。

每一个想要使用两次验证的用户需要在其用户目录生成一个密钥文件,使用命令 google-authenticator 来完成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$ 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:

Your new secret key is: J4T4C4HYT2KIA52WGSDJEOLM2I (验证器配置密钥)
Enter code from app (-1 to skip): 269371 (输入验证器生成的验证码)
Code confirmed
Your emergency scratch codes are: (紧急备用令牌码)
93394730
14394073
33491911
86112157
22174783

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
(是否拒绝多次重复使用相同的令牌?这将限制你每30s仅能登录一次,但会提醒/阻止中间人攻击。)

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
(是否将验证码有效窗口时间由1分30秒增加到约4分钟?这将缓解时间同步问题。)

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
(是否启用此模块的登录频率限制,登录者将会被限制为最多在30秒内登录3次。)

建议将备用令牌码保存在安全的地方(打印出来并放在一个安全的位置),因为当丢失手机(即你的两步验证器)或其他原因不能使用两步验证器时,只能使用备用令牌码登录。它们同时也被保存在~/.google_authenticator,你可以在登录后随时查阅。

设置二次验证器

在你的手机上安装两步验证器软件。例如:
Google Authenticator Google应用商店 / IOS.
在软件中创建一个新验证,输入密钥(如例子中的’J4T4C4HYT2KIA52WGSDJEOLM2I’)或扫描二维码来导入密钥,并依照屏幕提示输入验证码。

软件现在应该会显示一个每30秒更新的验证码。

测试验证

在完成测试前请不要断开目前已经的 SSH 连接!如果配置出错或者无法登陆还可以有补救的机会,否则失联的痛楚就要一人默默感受了!
现在请开启一个全新的终端,尝试 SSH 连接到完成了上述配置的主机,如果你配置了密码和二次验证,则下面的显示与你会有略微差别。
总之,尝试输入你的身份登录信息和二次验证码,若可以登陆系统,那恭喜你🎉!教程到此结束,下面的使一些其他玩法,若感兴趣请继续了解!

1
2
3
ssh username@你的服务器地址
Enter passphrase for key '/Users/username/.ssh/id_rsa': <输入密钥密码>
(username@你的服务器地址) Verification code: <输入二次验证码>

其他配置

用于桌面登陆

谷歌两次认证插件可以同时用于控制台与 GNOME 桌面登录。
只需要在文件 /etc/pam.d/login/etc/pam.d/gdm-password 内加入:
auth required pam_google_authenticator.so

存储位置

如果想要改变密钥存储位置,请使用 --secret 参数:

google-authenticator --secret="/PATH_FOLDER/USERNAME"
然后更改/etc/pam.d/sshd内的路径配置:

/etc/pam.d/sshd
1
auth required pam_google_authenticator.so user=root secret=/PATH_FOLDER/${USER}

user=root 用于强制PAM使用root用户权限来搜索文件。
另外请注意,密钥文件的所有者是root,生成文件的用户只能读取文件(chmod: 400):

chown root.root /PATH_FILE/SECRET_KEY_FILES
chmod 400 /PATH_FILE/SECRET_KEY_FILES