SSH多因素认证必须同时满足三件事:pam_google_authenticator.so正确加载、每个用户自行运行google-authenticator生成并保护好~/.google_authenticator、/etc/pam.d/sshd和/etc/ssh/sshd_config同步配置正确,缺一不可。

直接上结论:SSH 多因素认证(MFA)不是“装个包扫个码”就完事,必须同时满足三件事——pam_google_authenticator.so 正确加载、每个用户自己运行 google-authenticator 生成且保护好 ~/.google_authenticator、/etc/pam.d/sshd 和 /etc/ssh/sshd_config 同步改对,缺一不可;否则登录时只会静默失败或报 Authentication failure。
确认 pam_google_authenticator.so 是否真正可用
很多故障卡在这一步:模块看似装了,但 PAM 根本加载不了。错误日志里常见 pam_google_authenticator.so: cannot open shared object file。
- Debian/Ubuntu:检查
ls /lib/security/pam_google_authenticator.so,不存在就重装sudo apt install libpam-google-authenticator - RHEL/CentOS/Rocky 8+:先确认 EPEL 已启用(
sudo dnf install epel-release),再装sudo dnf install google-authenticator,模块路径是/usr/lib64/security/pam_google_authenticator.so - SELinux 启用的系统(如 RHEL 默认),可能拦截加载:临时用
sudo setenforce 0测试,若此时能过,说明需修复上下文,而非删 SELinux - 别信“包装成功”,一定要
ls看文件是否存在、路径是否匹配你的架构(x86_64 vs aarch64)
用户必须亲自运行 google-authenticator,且权限不能错
root 给其他用户代劳、复制 ~/.google_authenticator 文件、或让脚本批量生成——全都会失败。PAM 会因属主/权限不符直接跳过验证,日志只写 open() failed: Permission denied。
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
- 切到目标用户执行:
su - username(用su -,不是su,避免环境变量污染) - 运行
google-authenticator,关键选项必须选y:启用 TOTP、禁用重复使用码、启用速率限制(30 秒最多 3 次)、保存配置、生成恢复码 - 立刻检查:
ls -l ~/.google_authenticator必须是-rw-------(600),属主为该用户;否则 PAM 拒绝读取 - 10 个恢复码务必离线保存——手机丢了、文件损坏时,这是唯一能登进去的路
/etc/pam.d/sshd 的 auth 行位置和参数很关键
加错位置或参数不匹配,会导致 MFA 彻底失效:要么被跳过(仅密码生效),要么所有用户强制验证(包括还没初始化的用户,结果谁都登不进)。
- 备份原文件:
sudo cp /etc/pam.d/sshd /etc/pam.d/sshd.bak - 在文件**顶部**添加(Debian/Ubuntu 推荐):
auth [success=ok default=die] 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 - 绝对不要写
required——它会让未初始化用户的登录直接失败;nullok是容错开关,允许尚未配置 MFA 的用户暂用密码登录(上线后再逐个开通)
/etc/ssh/sshd_config 必须启用 ChallengeResponseAuthentication
只配 PAM 不够,SSH 本身得知道要“交互式提问”。漏掉这步,你输完密码就直接进去了,根本不会要验证码。
- 确保以下两行已取消注释并设为
yes:ChallengeResponseAuthentication yes和UsePAM yes - 如果只想对密码登录启用 MFA(保留密钥登录免二次验证),加这一行:
AuthenticationMethods password,keyboard-interactive;若想密钥 + 验证码组合,则用AuthenticationMethods publickey,keyboard-interactive - 改完必须重启服务:
sudo systemctl restart sshd(Ubuntu/Debian)或sudo systemctl restart sshd(RHEL/CentOS) - 测试前,新开一个终端连接——别用当前已登录的会话,否则无法验证流程是否真触发
最容易被忽略的是时间同步:TOTP 依赖精确时间,服务器与手机偏差超过 30 秒就会验证失败。别只靠 systemctl enable chronyd,还得确认 chrony.conf 里有 makestep 1 -1,让它能自动校正大偏差。

















