核心是pam模块pam_google_authenticator.so介入ssh登录验证:需正确安装模块、用户独立生成600权限的~/.google_authenticator文件、在/etc/pam.d/sshd中auth include password-auth上方添加auth [success=ok default=die] pam_google_authenticator.so nullok、并启用usepam yes与对应版本的challengeresponseauthentication/kbdinteractiveauthentication。

直接在 Linux 下为 SSH 启用基于 TOTP 的双因子认证,核心是让 PAM 模块 pam_google_authenticator.so 在登录时介入验证流程,不改底层逻辑、不装额外服务,只做最小必要配置。关键在于模块安装正确、用户密钥独立生成、PAM 规则位置合理、SSH 认证开关打开——四者齐备,才能触发验证码输入。
确认系统环境与模块安装
先查 OpenSSH 版本,决定后续配置写法:
- 运行
ssh -V:若显示OpenSSH_8.8或更高,说明需用AuthenticationMethods;低于该版本则用ChallengeResponseAuthentication - Debian/Ubuntu 执行:
sudo apt install libpam-google-authenticator,验证文件是否存在:ls /lib/security/pam_google_authenticator.so - RHEL/CentOS/Rocky 8+ 先启用 EPEL:
sudo dnf install epel-release,再装:sudo dnf install google-authenticator,检查路径:ls /usr/lib64/security/pam_google_authenticator.so - 若提示
cannot open shared object file,重点排查包名(CentOS 不是libpam-google-authenticator)、EPEL 是否启用、SELinux 是否拦截(可临时setenforce 0测试)
以目标用户身份生成密钥文件
root 不能代劳,也不能复制密钥文件。每个用户必须亲自初始化:
在 Go 中使用 google/wire 实现编译时依赖注入——wire.NewSet、wire.Build、wire.Bind(接口→实现)、wire.Struct、wire.Value、wire.Interface
- 切换到该用户:
su - username(或sudo -u username -i) - 运行:
google-authenticator -t -d -f -r 3 -R 30(-t禁用时间偏移容忍,-d强制 TOTP,-f强制写入,-r 33 次失败锁定,-R 3030 秒内拒绝重码) - 按提示选 y:启用时间令牌、禁用重用、启用速率限制、保存配置、生成恢复码——这 5 个应急码务必离线保存
- 执行后检查:
ls -l ~/.google_authenticator应为-rw-------(600),属主为当前用户;否则加chmod 600 ~/.google_authenticator - 同步服务器时间:
sudo timedatectl set-ntp true,TOTP 对时差敏感,超 30 秒即失效
配置 PAM 规则(顺序和参数决定是否生效)
编辑 /etc/pam.d/sshd,在 auth include password-auth 这一行的正上方添加:
auth [success=ok default=die] pam_google_authenticator.so nullok-
nullok表示未初始化的用户仍可登录(适合灰度上线);全面启用后可改为secret=/home/${USER}/.google_authenticator并去掉nullok,强制校验 - 切勿写成
required或放在password-auth下方——前者易导致模块异常时全员锁死,后者会因密码先通过而跳过验证 - 不要用
[success=done],它会让验证成功后直接跳过后续 auth 步骤(比如密码检查),破坏双因子逻辑
调整 SSH 服务配置并重启
编辑 /etc/ssh/sshd_config,确保以下三项开启:
-
UsePAM yes(必须,否则 PAM 配置不加载) -
ChallengeResponseAuthentication yes(OpenSSH KbdInteractiveAuthentication yes(8.8+) -
PasswordAuthentication yes(若用密码登录)或PubkeyAuthentication yes(若用密钥) - 如需强制双因子,加:
AuthenticationMethods publickey,keyboard-interactive(密钥 + 验证码)或keyboard-interactive(密码 + 验证码) - 修改前备份:
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak - 重启服务:
sudo systemctl restart sshd(reload不生效)
测试前保留一个已登录的终端会话,新开窗口执行 ssh user@host,确认先走第一因素(密码或密钥),再提示输入 6 位验证码。输错三次会触发 PAM 锁定,此时只能靠保留会话修复。










