Kenichi Maehashi's Blog

脳内コアダンプ

RSS
Category: Linux
Google Apps で利用可能になっている Google Authenticator による 2 要素認証ですが、実は PAM モジュールがオープンソースで公開されています。このモジュールを利用して、SSH サーバを Google Authenticator による 2 要素認証にしてみましょう。

メリット

  • 単一のパスワードではなくパスワード + ワンタイムパスワード(確認コード) の 2 要素で認証するため、パスワード漏洩時やブルートフォース攻撃に対するセキュリティ侵害リスクが低くなります。
  • iPhone や Android などのアプリケーションでワンタイムパスワードを生成できるためお手軽です。

注意点

PAM を使用して認証するため、公開鍵 + 確認コードの 2 要素認証にはできません (公開鍵のみの認証は引き続き可能です)。

導入手順

以下はすべて root を想定した作業です。環境に応じて su - や sudo などを使用してください。また、Development Tools や Development Libraries が前提となっています。

Mercurial の導入

Google Code からソースコードをチェックアウトするため、Mercurial (VCS) をインストールします。
事前に EPEL または RPMforge のセットアップが必要です。
yum -y install mercurial

ソースコードの取得

リポジトリをクローンします。
cd /usr/local/src
hg clone https://google-authenticator.googlecode.com/hg/ google-authenticator

Makefile の修正 (64-bit 環境の場合のみ)

Makefile を開きます。
vi /usr/local/src/google-authenticator/libpam/Makefile
3 箇所ある /usr/lib/libdl.so/usr/lib64/libdl.so に書き換えます。

コンパイルとインストール

cd /usr/local/src/google-authenticator/libpam
make
make install
/lib(64)/security/pam_google_authenticator.so と /usr/local/bin/google-authenticator がインストールされます。

PAM の設定

/etc/pam.d/sshd の設定は、デフォルトで以下のようになっています。
#%PAM-1.0
auth include system-auth
(account 以降は省略)
ここでは system-auth をインクルードしていますが、これでは不都合なので /etc/pam.d/system-auth から auth タイプの行をコピーしてきて展開します。特に認証連携を行っていない (UNIX 認証のみ) の場合は、以下のようになっているはずです。
auth        required      pam_env.so
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 500 quiet
auth required pam_deny.so
UNIX 認証に引き続いて Google Authenticator による認証を実行するため、pam_unix.so モジュールの control を sufficient から requisite に変更します。加えて、pam_google_authenticator.so モジュールを差し込みます。最終的に、/etc/pam.d/sshd は次のようになります。
#%PAM-1.0
auth required pam_env.so
auth requisite pam_unix.so nullok try_first_pass
auth sufficient pam_google_authenticator.so
auth requisite pam_succeed_if.so uid >= 500 quiet
auth required pam_deny.so
(account 以降は省略)

時間の設定

Google Authenticator を使用する場合、SSH サーバと Authenticator クライアント (スマートフォン) の時刻を合わせる必要があります (タイムゾーンは異なっても問題ないはずです)。ntpdate や date などで時間合わせを行っておいてください。

SSH サーバの設定

OpenSSH の設定 (/etc/ssh/sshd_config) を、少なくとも以下のように設定します。
  • PasswordAuthentication no (この設定が yes だと、1 要素認証ができてしまうため)
  • ChallengeResponseAuthentication yes (PAM による keyboard-interactive 認証を使用するため)
  • UsePAM yes (同上)
また、PermitRootLogin without-password の設定がされている場合、これは無視されます (root も 2 要素認証でログインできるようになる) ので、必要であれば PAM のルールで制限しましょう。ただし、root ユーザで Google Authenticator の設定 (下記) を行わない限り 2 要素認証はできませんので、あまり問題はないと思います。また、全てのユーザで、引き続き公開鍵認証を行うこともできます (公開鍵認証が先に行われた場合は Google Authenticator は無視されます)。

上記設定後、SSH サーバを再起動してください。
service sshd restart

ユーザごとの設定

Google Authenticator を使用してログインしたいユーザで /usr/local/bin/google-authenticator コマンドを実行すると、以下のように URL と、いくつかの質問が表示されます。
https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/kenichi@centos5%3Fsecret%3DXXXXXXXXXXXXXXXX
↑ この URL にアクセスすると、QR コードが表示されます。iPhone / Android の Google Authenticator アプリで読み込みます。
Your new secret key is: XXXXXXXXXXXXXXXX
Your verification code is 123456
Your emergency scratch codes are:
12345678
12345678
12345678
12345678
12345678
↑「バックアップコード」です。

Do you want me to update your "~/.google_authenticator" file (y/n) y
↑ ~/.google_authenticator ファイルを作成または更新します。更新した場合、QR コードの読み込みを再度行う必要があります。

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y
↑ 同じ認証コードを 2 回以上使えないようにします (中間者攻撃やリプレイ攻撃を防ぐため)。認証コードは 30 秒間同じものを使うため、30 秒以内に再度ログインすることはできなくなります。推奨値は y。

By default, tokens are good for 30 seconds and in order to compensate for
possible time-skew between the client and the server, we allow an extra
token before and after the current time. If you experience problems with poor
time synchronization, you can increase the window from its default
size of 1:30min to about 4min. Do you want to do so (y/n) n
↑ サーバとクライアントの時間のズレの許容値を、90 秒から 240 秒に増やします。時間がズレやすいホストの場合は y。通常の推奨値は n。

If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting (y/n) y
↑ 30 秒間に試行できるログインを 3 回までに制限します。推奨値は y。
ここまでで、設定は完了です。上記の URL を表示し、QR コードを iPhone や Android の Google Authenticator アプリで読み込みます。詳しくは Installing Google Authenticator (日本語) を参照してください。
また、バックアップコードについては Signing in using backup codes (日本語) を参照してください (Google Authenticator アプリが使用できない、緊急の場合にのみ使用するコードです。メモしておきましょう)。

ログイン!

お手近の SSH クライアントから:
$ ssh kenichi@10.0.123.123
Password: <= アカウントの UNIX パスワードを入力
Verification code: <= Google Authenticator アプリから入手したワンタイムパスワードを入力
Last login: Thu Jan 1 12:34:56 2011 from 10.0.123.100
[kenichi@centos5 ~]$
というわけで、ログインできました。Password を間違えた場合は、Verification code のプロンプトが出ないはずです (Google Apps でも、このようになっています)。Verification code を間違えた場合は、Password からやり直しです。

公開鍵が使われてしまって実験できない場合は、~/.ssh/authorized_keys を退避するか、
ssh -o PubkeyAuthentication=no kenichi@10.0.123.123
とすれば良いでしょう。

備考

PAM の設定次第で、コンソールログインに Google Authenticator を使うこともできます (どちらかというと、こちらの方が SSH の設定よりも簡単ですね)。ただ、system-auth はログインだけでなく su - などにも影響を与えるので、設定内容には注意が必要です。
なお、authconfig / authconfig-tui を実行すると system-auth-ac が書き換えられてしまうので、注意してください (心配であれば、system-auth から system-auth-ac のシンボリックリンクを外してコピーしてしまうと良いでしょう。ただし、推奨はしません)。

また、今回は UNIX 認証を requisite としましたが、サーバにブルートフォース攻撃への対策を全く行っていない場合は required が良いかもしれません (この場合、Password の適否に関わらず Verification code プロンプトが表示されます)。
Password と Verification code の順序を逆にするのもオモシロイですね!

Comments

Leave Yours...
Name:
E-mail / URL (optional):
Comment:
Are You Robot?: