«前の日記(2014-10-06 (Mon)) 最新 次の日記(2014-11-11 (Tue))» 編集

雑記帳


2014-10-15 (Wed) [長年日記]

[Linux] SSHの認証でワンタイムパスワードを使う(ログインするたびに何度も入力するのが嫌な人への対策編)

SSHの認証でワンタイムパスワードを使う(導入編)では、Google AuthenticatorのPAMモジュールを使って、SSHする際にワンタイムパスワードを使うというのを実践した。

また、GSSAPIとGoogle Authenticatorを連動させるでは、SSHする際に、Kerberos認証をした結果をGSSAPIを使ってSSOするようにした。

これによって、ワンタイムパスワードを入力するだけでログインできるようになった。しかし、SSHするたびにワンタイムパスワードを入力するのが面倒である、というフィードバックがあった。例えば、EvernoteやGoogle Appsなどのサービスは、必ずしもワンタイムパスワードを毎回入力する必要がなく、認証情報を記録しておき、一定期間はワンタイムパスワードの入力は不要になる、という仕組みが存在する。ワンタイムパスワードを使うことによってセキュリティを強化しても、使い勝手が悪いと利用されなくなってしまうからだろう。

残念ながら、Google AuthenticatorのPAMモジュール自体に、それに相当する機能は存在しない。別の方法が無いか調べているうちに、pam_timestampというPAMモジュールがあることに気がついた。pam_timestampは、sudoコマンドがパスワードを入力した後、しばらくはパスワードを入力せずとも実行できる仕組みをシミュレートするものという。まさに今回実現したいことが実現できそうだ。

というわけで、/etc/pam.d/sshdに設定してみた。ドキュメントに従って、authとsessionに、pam_timestamp.soを追加している。

#%PAM-1.0
auth required pam_sepermit.so
auth sufficient pam_timestamp.so timestamp_timeout=300
auth substack google-auth
auth include postlogin
account required pam_nologin.so
account include password-auth
password include password-auth
# pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session required pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session required pam_selinux.so open env_params
session optional pam_keyinit.so force revoke
session optional pam_timestamp.so
session include password-auth
session include postlogin

この設定の意図は、sshdでgoogle-authenticatorにて認証を行う前に、それより5分以内に認証に成功していれば、再度ワンタイムパスワードの入力は不要になる、というところだ。

ということで、この設定でテストしてみた。

初回のログイン時には、ワンタイムパスワードを入力してログインできた。この際、timestampを記録するファイルが更新されることが分かる。

Oct 15 16:21:34 test sshd[27283]: pam_timestamp(sshd:session): updated timestamp file `/var/run/sudo/root/ssh:isobe'

では、2回目はどうかと思いログインしてみたが、再度ワンタイムパスワードの入力が求められてしまった。どういうことなのか、ログを見てみる。

Oct 15 16:22:19 test sshd[27425]: pam_timestamp(sshd:auth): timestamp file `/var/run/sudo/root/ssh:isobe' is older than oldest login, disallowing access to sshd for user root

oldest loginの時刻とファイルのtimestampを比較して、login時刻よりもtimestampが古いので許可しない、ということのようだ。ソースコードを見てみると、check_login_time関数でそのチェックを行なっているらしい。どうやら、sudoの動きをシミュレートしているからか、ログインをしている状態で利用されることが前提になっているようだ。

少し考えた末、check_login_time関数を無力化すれば、やりたいことができるのではないかと思った。

というわけで、ソースコードを下記のように修正。check_login_timeの中身を削除して、PAM_SUCCESSを返すだけにした。また、デフォルトでtimestampを記録するディレクトリが、/var/run/sudoだったので、/var/run/google-authに変更したり、モジュール名をpam_timestamp_gauthに変更したりしてる。

ということで、これをmakeして出来たpam_timestamp.soを、/var/lib64/security/pam_timestamp_gauth.soにmvして、/etc/pam.d/sshdを、下記のように修正した。timestamp_timeoutは、テスト目的のため、60秒と短くしている。

#%PAM-1.0
auth required pam_sepermit.so
auth sufficient pam_timestamp_gauth.so timestamp_timeout=60 verbose
auth substack google-auth
auth include postlogin
account required pam_nologin.so
account include password-auth
password include password-auth
# pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session required pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session required pam_selinux.so open env_params
session optional pam_keyinit.so force revoke
session optional pam_timestamp_gauth.so
session include password-auth
session include postlogin

これで、再度テストしてみる。

% ssh test.example.local
Authenticated with partial success.
Verification code:
Last login: Wed Oct 15 19:14:15 2014 from 192.168.22.96
$ exit
ログアウト
Connection to test.example.local closed.
% ssh test.example.local
Authenticated with partial success.
Access granted (last access was 6 seconds ago).
Last login: Wed Oct 15 21:46:58 2014 from 192.168.22.96
$

おお、"Access granted (last access was 6 seconds ago)."と出力され、ワンタイムパスワードを入力せずともログインできた。ログを見ると、下記のように記録されている。

Oct 15 21:47:04 test sshd[5051]: pam_timestamp_gauth(sshd:auth): timestamp file `/var/run/google-auth/root/ssh:isobe' is only 6 seconds old, allowing access to sshd for user root

そして、設定した時間を越えて、再度ログインすると、通常通り、ワンタイムパスワードの入力が求められる。ログには、下記のように出力される。

Oct 15 21:48:38 test sshd[5185]: pam_timestamp_gauth(sshd:auth): timestamp file `/var/run/google-auth/root/ssh:isobe' has unacceptable age (94 seconds), disallowing access to sshd for user root

timestamp_timeoutの秒数を適切に変更すれば、比較的ストレス無く利用できるようになるだろう。