雑記帳
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の秒数を適切に変更すれば、比較的ストレス無く利用できるようになるだろう。