2026年5月28日
2026年5月28日
SSHの2段階認証をGoogle Authenticatorで設定する方法|公開鍵とワンタイムコード
SSH のログインに、スマートフォンの認証アプリ(Google Authenticator、Microsoft Authenticator など)が 30 秒ごとに表示する 6 桁のコード(TOTP)を加えると、秘密鍵やパスワードが漏れても、それだけではログインできなくなります。
サーバー側で使うのは、Google が公開している PAM モジュール pam_google_authenticator.so です。アプリはサーバーに入れるものではありません。流れは次のとおりです。
- サーバーに PAM モジュールを入れる
- ログインするユーザーごとに
google-authenticatorコマンドで秘密鍵を作り、アプリに登録する /etc/pam.d/sshdとsshd_configを設定して、SSH の認証にコードの入力を加える
この記事では「公開鍵認証に成功したうえで、さらにコードを入力する」構成を作ります。Debian 13(OpenSSH 10.0、libpam-google-authenticator 20191231)で、正しいコードでログインでき、誤ったコードと鍵なしでは拒否されることを確認しました。AlmaLinux 9 ではパッケージと設定ファイルの構成を確認しています(2026年11月時点)。
始める前に
- 今つないでいる SSH の接続は、最後の確認が終わるまで閉じないでください。 設定を誤ると新しくログインできなくなります。VPS の管理画面にあるコンソール(ブラウザーから操作できる画面)の使い方も確認しておきます。
- 公開鍵認証でログインできる状態にしておきます。まだの場合は SSHの公開鍵認証を設定する方法 を先に済ませます。
- TOTP はサーバーの時計がずれていると合いません。時刻が同期されているか確認します。
timedatectl
# System clock synchronized: yes になっていれば同期されている
1. PAM モジュールを入れる
# Debian / Ubuntu
sudo apt update
sudo apt install libpam-google-authenticator
# AlmaLinux / Rocky Linux / RHEL 9(EPEL のパッケージ)
sudo dnf install epel-release
sudo dnf install google-authenticator
パッケージ名に注意してください。Debian/Ubuntu では libpam-google-authenticator、RHEL 系では EPEL の google-authenticator です。どちらにも、秘密鍵を作る google-authenticator コマンドと PAM モジュールが入ります。
2. ユーザーごとに秘密鍵を作る
2 段階認証を使うユーザー自身で実行します(sudo を付けない)。root で実行すると root 用の設定ができます。
google-authenticator
対話形式で質問が出ます。時間ベース(TOTP)にするかに y と答えると、端末に QR コードと秘密鍵(英大文字と数字の文字列)が表示されます。
- 認証アプリで QR コードを読み取る(読み取れない場合は秘密鍵を手で入力する)
Enter code from app (-1 to skip):に、アプリに表示されたコードを入力する- 表示された緊急用コード(8 桁、既定で 5 個)を、サーバーの外の安全な場所に控える
- 続く質問(設定ファイルの更新、コードの再利用の禁止、許容する時刻のずれ、試行回数の制限)に答える
質問に答える代わりに、オプションでまとめて指定することもできます。
google-authenticator -t -d -f -r 3 -R 30 -w 3
| オプション | 意味 |
|---|---|
-t |
時間ベース(TOTP)にする |
-d |
同じコードの再利用を禁止する |
-f |
確認せずに ~/.google_authenticator に書き込む |
-r 3 -R 30 |
30 秒あたり 3 回までに試行を制限する |
-w 3 |
前後 1 つずつのコードまで受け付ける(時計のずれの許容) |
この指定でも、QR コードの表示とアプリのコードの確認(Enter code from app)は行われます。
設定は ~/.google_authenticator に保存されます。1 行目が秘密鍵、" で始まる行が設定、残りの 8 桁の行が緊急用コードです。このファイルが漏れるとコードを作れてしまうので、権限(-r--------、本人だけが読める)を変えないでください。
3. PAM の設定(/etc/pam.d/sshd)
設定ファイルを編集する前に、元のファイルを控えておきます。
sudo cp /etc/pam.d/sshd /etc/pam.d/sshd.bak
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
/etc/pam.d/sshd の末尾に次の 1 行を加えます。
auth required pam_google_authenticator.so
公開鍵とコードの組み合わせにする場合は、パスワードの入力を求める行をコメントにします。コメントにしないと、コードに加えて Linux のパスワードも聞かれます。
# Debian / Ubuntu の場合
#@include common-auth
# AlmaLinux / RHEL 系の場合
#auth substack password-auth
まだ設定していないユーザーの扱い
~/.google_authenticator が無いユーザーは、この設定ではログインできなくなります(確認環境でも、ファイルの無いユーザーは鍵が正しくても拒否されました)。全員の設定が終わるまでの移行期間は、公式の README にある nullok を付けると、ファイルが無いユーザーはコードなしで通せます。
auth required pam_google_authenticator.so nullok
全員の設定が済んだら nullok を外します。
4. sshd の設定
/etc/ssh/sshd_config.d/ に新しいファイルを作ります。sshd は同じ設定項目が複数あると最初に読んだ値を使うため、既存のファイルより先に読まれる名前(数字の小さい名前)にします。
sudo nano /etc/ssh/sshd_config.d/01-2fa.conf
KbdInteractiveAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
KbdInteractiveAuthentication yes:PAM がコードの入力を求められるようにする。古い設定名ChallengeResponseAuthenticationは、これの別名で非推奨AuthenticationMethods publickey,keyboard-interactive:公開鍵認証に成功し、さらにキーボード入力(ここではコード)の認証にも成功したときだけログインを許すUsePAM yesが必要です。Debian・Ubuntu・AlmaLinux の標準の設定ではすでに有効です
AlmaLinux 9 では /etc/ssh/sshd_config.d/50-redhat.conf に ChallengeResponseAuthentication no があります。ファイル名を 60-2fa.conf にすると、こちらが後から読まれて無視され、確認環境では sshd -T(設定の確認)で次のエラーが出ました。
Disabled method "keyboard-interactive" in AuthenticationMethods list "publickey,keyboard-interactive"
AuthenticationMethods cannot be satisfied by enabled authentication methods
設定を確かめてから sshd を再起動します。
sudo sshd -t
sudo sshd -T | grep -E "^(usepam|kbdinteractiveauthentication|authenticationmethods)"
usepam yes
kbdinteractiveauthentication yes
authenticationmethods publickey,keyboard-interactive
# Debian / Ubuntu
sudo systemctl restart ssh
# AlmaLinux / RHEL 系
sudo systemctl restart sshd
5. 別の端末からログインを確かめる
今の接続を開いたまま、手元のパソコンで新しい端末を開いてログインします。
ssh user@サーバーのアドレス
公開鍵認証のあとに次の表示が出て、アプリのコードを入れるとログインできれば成功です。
(user@203.0.113.10) Verification code:
確認環境での結果は次のとおりでした。
| 試したこと | 結果 |
|---|---|
| 正しい鍵 + 正しいコード | ログインできた |
| 正しい鍵 + 誤ったコード | Verification code: が再表示され、ログインできなかった |
鍵を使わない(-o PubkeyAuthentication=no) |
Permission denied (publickey). で拒否された |
~/.google_authenticator の無いユーザー(nullok なし) |
Permission denied (keyboard-interactive). で拒否された |
うまくいかないときは、ログを見ます。Debian/Ubuntu では /var/log/auth.log または journalctl -u ssh、RHEL 系では /var/log/secure または journalctl -u sshd に、pam_google_authenticator の記録が残ります。
sshd(pam_google_authenticator)[1166]: Invalid verification code for user
確認が終わるまでは、最初の接続を閉じないでください。ログインできない場合は、最初の接続から /etc/pam.d/sshd.bak と sshd_config.bak を戻し、01-2fa.conf を削除して sshd を再起動します。
スマートフォンをなくしたとき
- 緊急用コード:
Verification code:に 8 桁の緊急用コードを入れるとログインできます。各コードは 1 回だけ使えます。 - 再設定:ログインしたら、本人が
google-authenticatorを実行し直すと新しい秘密鍵と緊急用コードが作られ、古いアプリの登録は使えなくなります。 - 誰もログインできない場合:VPS の管理画面のコンソールからログインし、
/etc/pam.d/sshdのpam_google_authenticator.soの行をコメントにします。
複数のスマートフォンに登録しておきたい場合は、最初に QR コードを表示したときにそれぞれのアプリで読み取ります。
注意点
- SFTP や rsync などで鍵だけを使って自動でログインしている処理も、コードを求められて失敗します。自動処理に使うユーザーを分け、
Match UserでAuthenticationMethods publickeyを指定するなどの対応が必要です。 - 同じ秘密鍵の情報(
~/.google_authenticator)をバックアップする場合、そのバックアップも鍵と同じ扱いで保護します。 - 公開鍵認証を使うなら、パスワードでのログインも止めておくと安全性が上がります。手順は SSHのパスワード認証を無効化する方法 で説明しています。