ssh多因子验证必须同时满足三项条件:challengeresponseauthentication设为yes、usepam开启、用户本人运行google-authenticator生成密钥,缺一不可;否则登录将静默跳过验证码,仅执行密码或密钥验证。

SSH 多因子验证不是装个 App 就能生效的——ChallengeResponseAuthentication 必须设为 yes,UsePAM 必须开启,且 google-authenticator 密钥必须由用户本人运行生成,三者缺一不可。否则登录时静默跳过验证码,你以为开了 MFA,其实只走了密码或密钥那一关。
为什么 SSH 登录不弹验证码?
最常见原因是 OpenSSH 默认禁用 PAM 的交互式二次验证。即使 PAM 配置写了、模块也装了、App 也绑了,只要没打开开关,就永远不会触发输入 OTP 的环节。
-
ChallengeResponseAuthentication yes是硬性要求,写成on或漏掉都不行 -
UsePAM yes必须存在且未被注释,否则 PAM 规则根本不会加载 - 如果同时启用了公钥登录(
PubkeyAuthentication yes),还需加一行:AuthenticationMethods publickey,keyboard-interactive,否则密钥认证成功后直接放行,跳过后续验证 - 改完配置必须
sudo systemctl restart sshd,reload不会重载 ChallengeResponseAuthentication 状态
用户级密钥生成容易踩哪些坑?
root 不能代劳,也不能复制 .google_authenticator 文件过去——PAM 会因权限或属主不符直接忽略该用户验证。
- 必须切换到目标用户再执行:
su - username→google-authenticator - 关键选项建议全选
y:启用 TOTP、禁用重复码、启用速率限制(30 秒最多 3 次)、保存配置、生成恢复码 -
ls -l ~/.google_authenticator必须显示-rw-------(600 权限),否则日志里只有open() failed: Permission denied - 恢复码务必离线存好——手机丢了、文件损坏了,这是唯一能登进去的路
/etc/pam.d/sshd 的 auth 行怎么写才对?
顺序和参数错一个,就可能变成“所有人强制 MFA”或“所有人跳过 MFA”。Debian/Ubuntu 和 RHEL 系统路径、参数习惯不同,不能照搬。
- Debian/Ubuntu 推荐写在文件顶部:
auth [success=ok default=bad] pam_google_authenticator.so nullok secret=/home/${USER}/.google_authenticator - RHEL/CentOS 更稳妥写法:
auth [success=ok new_authtok_reqd=ok default=bad] pam_google_authenticator.so nullok secret=/home/%u/.google_authenticator -
nullok表示未初始化.google_authenticator的用户可跳过这步(灰度上线时有用);上线后建议去掉,强制所有用户完成绑定 - 不要用
required——它会让整个 auth 栈失败时立即终止,而[success=ok default=bad]才能与密码/密钥组合生效
模块没加载成功?先查这三件事
pam_google_authenticator.so: cannot open shared object file 这类错误,90% 出在安装或路径上,而不是配置本身。
- Debian/Ubuntu:检查
ls /lib/security/pam_google_authenticator.so是否存在;若无,sudo apt install libpam-google-authenticator - RHEL/CentOS/Rocky:先确认 EPEL 已启用(
sudo dnf install epel-release),再装google-authenticator(不是libpam-google-authenticator),模块路径通常是/usr/lib64/security/pam_google_authenticator.so - SELinux 可能拦截:临时
sudo setenforce 0测试,若恢复正常,需调整上下文或添加策略,而非永久关闭
真正麻烦的不是配置步骤,而是各环节之间的依赖关系:PAM 模块加载失败 → 验证不触发;用户没自己跑 google-authenticator → 文件权限错或路径空;sshd_config 里少一行 AuthenticationMethods → 公钥用户永远收不到验证码。每个点都得实打实验证,不能假设“应该没问题”。











