話題の記事

Amazon LinuxへのsshをGoogle Authenticatorを用いて二段階認証にしてみた

2015.10.03

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは植木和樹@上越妙高オフィスです。今日はAmazon Linuxへのsshログイン時におけるセキュリティ強化のお話です。

AWS運用チェックリストではOSにログインする際のユーザーは共有せず、個人ごとにOSアカウントを作成することが推奨されています。

個人ごとにOSアカウントを作成すれば、いつ誰がそのサーバーにログインしたのか分かるので不正な操作が行われた際のトレースに役立ちます。

しかし仮にパソコンが盗まれる等で秘密鍵が盗まれてしまった場合を想定し、さらにもう一段階、その人のみが持っているものを用いなければサーバーにログインできない仕掛けを作ってみます。これを2段階認証といいます。今回は 1.個人のssh鍵ファイル + 2.スマホに表示されるワンタイムパスワード、の2つで設定してみました。

Google Authenticatorのインストール

ワンタイムパスワードによる認証にはGoogle Authenticatorを利用しました。

google/google-authenticator

サーバーにはAmazon Linux (2015.09)を使用しました。AWS公式リポジトリにRPMで提供されていますので、yumコマンドでインストールが可能です。ここではGoogle AuthenticatorにてQRコードによる設定を有効にしたいのでqrencodeライブラリも一緒に入れています。

sudo yum install google-authenticator qrencode-libs -y

クライアントはGoogle Authenticatorアプリでも良いですが、Authyや1Password (Pro)などワンタイムパスワードの対応しているアプリでもOKです。

サーバー側の設定

サーバー側の設定は大きく3箇所を修正します。

  1. sshd の設定ファイル(/etc/ssh/sshd_config)
  2. sshd のPAM設定ファイル(/etc/pam.d/sshd)
  3. ログイン時のbash profileファイル(/etc/profile.d/google-authenticator)

sshd の設定ファイル

sshd_config はChallengeResponseAuthenticationが初期設定でnoになっていますが、これをyesに変更します。これによりssh鍵ファイル認証だけでなく、キーボードからの入力を用いた認証も可能になります。

/etc/ssh/sshd_config (修正箇所)

$ grep \
 -e ^PasswordAuthentication \
 -e ^ChallengeResponseAuthentication \
 -e ^UsePAM \
 /etc/ssh/sshd_config
PasswordAuthentication no
ChallengeResponseAuthentication yes
UsePAM yes

さらに下記の設定を追記します。もしものためにec2-userは鍵認証のみでのログインを可能にし、それ以外のユーザーでのみ鍵認証+ワンタイムパスワード認証を有効にしておきます。

/etc/ssh/sshd_config (追記箇所)

AuthenticationMethods publickey,keyboard-interactive
Match User ec2-user
   AuthenticationMethods publickey
   PubkeyAuthentication yes
   PasswordAuthentication no

設定を修正したら sshd を再起動しましょう。

$ sudo service sshd restart

sshd のPAM設定ファイル

前の手順で、sshのパスワードによる認証が有効になりました。次にPAMの設定を修正し、sshログイン認証時にGoogle Authenticatorが使われるようにします。

まずは下記の内容で /etc/pam.d に新しい設定ファイルを作成します。

/etc/pam.d/google-auth

#%PAM-1.0
auth        required      pam_env.so
auth        sufficient    pam_google_authenticator.so nullok
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        required      pam_deny.so

設定は上から順に評価されていきます。

  • 2行目は環境変数を読み込むおまじない
  • 3行目でGoogle Authenticatorを有効にしています。soファイルは /lib64/security/ から読み込まれます。nullok オプションをしているため初回ログインでGoogle Authenticatorを初期化(後述)していない場合はここでの認証処理はパスされます。
  • 3行目は sufficient を指定しているのでGoogle Authenticatorによる認証がOKならログインが可能になります。
  • 4行目はログインユーザーの uid が500以上(一般ユーザー)であることを強制してしています。requisiteしていているのでuidが500未満の人はここでログインが拒否されます。(なおこの行に到達するのは4行目で説明した初回ログイン時だけです)
  • 認証がNGなら5行目でログインが拒否されます。

次にsshdのPAM設定を修正します。初期設定でpassword-authが有効になっているのでこれをコメントアウトし、先ほど作成した google-auth と入れ替えましょう。

/etc/pam.d/sshd

#%PAM-1.0
auth	   required	pam_sepermit.so
#auth       substack     password-auth
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    include      password-auth
session    include      postlogin

ログイン時のbash profileファイル

ユーザーがログインした時に強制的なGoogle Authenticatorの初期化を有効にするため、/etc/profile.d に下記内容でファイルを作成します。

/etc/profile.d/google-authenticator.sh

#!/bin/sh

if [ "$USER" != "root" -a "$USER" != "ec2-user" ]; then
  if [ ! -f "$HOME/.google_authenticator" ]; then
    # 2018/03/12 いただいたコメントを反映し、初期化処理の前後のみトラップするよう修正しました
    trap 'exit' SIGINT
    echo "google-authenticator の初期設定を行います"
    /usr/bin/google-authenticator -t -d -W -u -f
    trap -- SIGINT
  fi
fi

INTシグナルをトラップして exit しているため、認証途中でCtrl+Cすると強制ログアウトします。

なお google-authenticator コマンドに渡しているオプションは次の意味があります。

-t
時刻ベースのワンタイムパスワードを生成する。
-d
一度利用したワンタイムパスワードの再利用を禁止する。時刻ベースのため30秒経過しないと新しいワンタイムパスワードが生成されません。これにより連続して同一サーバーへログインはできなくなります。
-W
認証コードを有効とする時刻のズレを最小にする。サーバーとクライアントの時刻ズレは90秒までなら許容されます。
-u
一定時間内のログイン回数制限を行わない。有効にした場合の初期設定は30秒間に3回までに制限されます。
-f
確認なしでユーザーホームディレクトリの設定ファイルを上書きする。

コマンドラインオプションを付けなければ対話的に設定ができますが、今回はこちらで指定することにしました。

ログインしてみる

ec2-userのログインユーザーを作成して、ssh鍵認証の設定をしたらログインしてみます。

20151003_gauth_001

でかっ!!

qrencodeライブラリでQRコードが表示されます。これをスマホに入れたGoogle Authenticatorアプリ(またはAuthyや1Password)のカメラで撮って設定しましょう。 設定が終わったら一旦ログアウトします。再度ログインすると今度はワンタイムパスワード認証が有効になります。

20151003_gauth_002

いいですね!

まとめ

Google Authenticatorを利用して二段階認証をAmazon Linuxに設定してみました。 PCIDSSでは、カード情報を取り扱うサーバーへのログイン時に二段階認証を要求します。Amazon Linuxなら上記の通り認証ライブラリがyumで提供されていますし、ワンタイムパスワードもAWSマネージメントにMFAを設定していることで慣れていると思いますので簡単に導入できそうですね。

またすべてのサーバーを二段階認証に対応させるのではなく、踏み台サーバーのみに設定して管理を楽にする方法も考えられると思います。もちろん各サーバーは踏み台サーバー経由のみsshログインを許可するようセキュリティグループで制限することをお忘れなく。

それではサーバーを安全に保って、快適なAmazon Linuxライフを!

参考にしたサイト