为 Linux 主机配置动态密码
为 Linux 主机的 SSH 登录增加一层动态验证码校验,可以降低密码或私钥泄露后被直接登录的风险。本文以使用 DNF 的 Linux 系统为例,通过 Google Authenticator 和 PAM 配置基于时间的一次性密码(TOTP),使用 Microsoft Authenticator 扫码生成验证码,并介绍密码或密钥搭配动态码的配置方式。
部署动态密码
1. 安装软件包
sudo dnf install -y epel-release # RHEL 上如果装不了,用:# sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpmsudo dnf install -y google-authenticator qrencode2. 为要登录的用户生成密钥(用该用户身份执行,不要用 sudo)
google-authenticator -t -d -f -r 3 -R 30 -w 3- 终端会显示一个二维码和几个应急恢复码。在 Microsoft Authenticator 里点扫这个二外码,会自动生成和 hostname 名称相同的令牌。
- 应急码要另外保存好。密钥写在
~/.google_authenticator里。
3. 配置动态密码登录
⚠️ 开始前先另外开一个 root 的 SSH 会话,并且全程不要关掉。 配置出错时可以用它回滚,避免让自己也无法登录。
- 编辑
/etc/pam.d/sshd,在auth substack password-auth这一行上方增加如下配置
auth required pam_google_authenticator.so- 配置 sshd,在
/etc/ssh/sshd_config.d/下新建一个文件,叫做40-mfa.conf,填入
KbdInteractiveAuthentication yesUsePAM yesAuthenticationMethods keyboard-interactive其中AuthenticationMethods keyboard-interactive表示同时启用密码和动态密码登录,如果需要使用密钥+动态码,可以修改为AuthenticationMethods publickey,keyboard-interactive;
如果使用密钥+动态密码的认证形式,还需要在/etc/pam.d/sshd 里注释掉 auth substack password-auth,否则登录时仍然会要求输入密码。
4. 检查配置并重启 sshd
sudo sshd -t && sudo systemctl restart sshd然后新开一个终端测试登录,应该会先提示 Password:(或者直接用密钥认证),再提示 Verification code:,如图:

常见问题
1. 确保时间同步正确
虚拟机的时间必须准确,TOTP 依赖时间同步。用 timedatectl 确认 System clock synchronized: yes,没有同步的话启用 chronyd。
在内网环境里可以先搭建一个 NTP 服务器从权威 NTP 获取时间,然后内网服务器从这台内部 NTP 中同步时间
2. 豁免用户
如果想要让尚未完成 mfa 配置的用户能正常登录,可以在
auth required pam_google_authenticator.so这行配置最后,增加nullok,这样就只有已经完成 mfa 配置的用户强制使用动态密码,尚未配置的用户仍可以正常登录;不过最佳实践是直接强制开启动态密码,尚未配置的用户让管理员手动用su - <username>切换用户,生成二维码,然后给用户来扫。
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!

