SSH OTP

使用 Linux PAM 和 Google Authenticator 的 PAM 模块,为 SSH 登录添加基于时间的一次性验证码。

执行前须知

此 Ubuntu 示例需要安装额外的 PAM 模块,并修改服务器认证方式。请保持现有管理员会话打开,并准备独立控制台或其他恢复入口。强制启用前,逐个配置并测试需要登录的账号;妥善保管 OTP 密钥和紧急恢复码,切勿公开。确保服务器时间同步,并确认 SSH 客户端支持键盘交互提示,以及自动化和恢复账号仍可使用。示例保留 common-auth,可能同时要求系统密码和 OTP;公钥加键盘交互不一定恰好产生两个提示或两种认证因素。PAM 文件、策略和服务名称因发行版而异,不要将此示例直接用于 macOS 或 Windows 服务器。

修改生效后,请先通过新的 SSH 会话确认可以正常登录,并验证预期功能。在确认成功之前,请保持当前会话打开,以便必要时恢复配置。

身份验证器

在手机上使用支持 TOTP 的身份验证器扫描注册二维码,或手动输入密钥。请保护好二维码和密钥,并妥善保存紧急恢复码。手机验证器与服务器上的 PAM 模块是不同的软件。

2FAS 提供可选备份;多设备同步属于 Premium 功能,具体支持情况取决于平台和方案。

使用示例

在 Ubuntu 上安装 PAM 模块。该模块独立于 OpenSSH,并且需要管理员权限。

sudo apt update
sudo apt install libpam-google-authenticator

以每个需要 OTP 的账号运行注册工具。按照提示将账号添加到验证器应用,并妥善保存紧急恢复码;不要分享或记录显示的密钥。

google-authenticator

在现有 SSH PAM 服务文件(通常是 /etc/pam.d/sshd)中增加该 auth 规则,保留已有的 account、session 等规则。以下只是片段;保留 common-auth 可能还会要求系统密码。需要强制 OTP 时不要添加 nullok。

使用 nano 打开文件:

sudo nano /etc/pam.d/sshd
@include common-auth
auth required pam_google_authenticator.so

将这些设置合并到实际生效的 SSH 服务器配置中,要求公钥及 PAM 键盘交互认证。已有 Include 顺序或 Match 块可能影响结果;不要覆盖整个配置文件。

使用 nano 打开文件:

sudo nano /etc/ssh/sshd_config
UsePAM yes
PubkeyAuthentication yes
KbdInteractiveAuthentication yes
PasswordAuthentication no
AuthenticationMethods publickey,keyboard-interactive:pam

按系统的 SSH 服务流程重新加载前,验证语法并检查生效配置。涉及 Match 时,使用 sshd -T -C 指定相应用户和来源地址。在单独会话中验证密钥及全部提示的认证步骤成功后,再关闭原会话。

sudo sshd -t && sudo sshd -T && sudo systemctl reload ssh

可选:公钥加 OTP

若希望公钥之后只输入 OTP、不再输入账号密码,需要相应调整 SSH 的 PAM auth 规则。从 SSH PAM 服务中移除 common-auth 会影响使用该服务的所有账号,并可能绕过其他认证策略。请与管理员检查剩余 auth 规则,保留 account 和 session 规则,始终保留现有登录会话及独立恢复入口。

以下是 Ubuntu SSH PAM 服务的示意片段,不是完整文件。确认影响后,才可在现有文件中注释 common-auth;不要添加 nullok。其他 auth 规则仍可能要求额外认证。

使用 nano 打开文件:

sudo nano /etc/pam.d/sshd
# /etc/pam.d/sshd: auth fragment only
# @include common-auth
auth required pam_google_authenticator.so

合并上面的 SSH 设置后,检查实际生效的值;输出中的键名为小写。Include 顺序和 Match 块可能改变结果,涉及 Match 时请使用 sshd -T -C 并指定相关连接条件。

sudo sshd -T | grep -E '^(usepam|pubkeyauthentication|kbdinteractiveauthentication|passwordauthentication|authenticationmethods) '

使用上面的命令验证并重载。从另一台客户端的新会话,使用已注册账号和私钥连接,然后输入验证器中的验证码。确认缺少必需的密钥或验证码时无法登录,再关闭原会话。实际提示取决于完整 PAM 策略。

ssh -i ~/.ssh/id_ed25519 alice@server.example.com

Secure Pipes 支持 SSH keyboard-interactive 提示,可输入服务器要求的验证码;这与 Secure Pipes 的应用解锁 OTP 是两回事。OTP 共享密钥保存在服务器及验证器应用中,Secure Pipes 不需要为该 SSH 登录保存密钥。

权威参考

核对日期:2026 年 10 月 27 日