PhoneFactor改めAzure MFA ServerってAD FSの2段階認証をオンプレで構成する場合くらいでしか利用されているのを見たことがないのですが、実はものすごく器用なプロダクトなので、色々と活用して行こう、というのが今回の主旨です。
そもそもAzure MFA Serverはがどう言うものかを一言で説明すると、「多要素認証付きのマルチプロトコル対応の認証サーバ」です。例えば、LDAPやRadius、Windows認証などに対応しています。
今回はタイトルに書いた通り、その中のRadiusサーバとしての機能を使って、LinuxへのSSHでのログインの時の認証の2要素目としてMicrosoft AuthenticatorアプリやSMS通知などを使えるようにしてみます。
以下の様な環境です。
ちなみに、Azure MFA ServerをLDAPサーバとして構成してLinux側はpam_ldapを使う、という選択肢もなくはないのですが、レポジトリにActive Directoryを使ったのでpam_ldapが認証対象のユーザのDNを取得する前に行うbindの段階で2要素認証が走ってしまうので、実際は使えないなぁ、ということで辞めました。匿名bindに対応したLDAPサーバを使えば行けるかもしれません。(Active Directoryを匿名bind化することも可能ではありますが、お奨めできないので)
早速やってみましょう。
◆Linux側の準備物
今回はAzure IaaS上のCentOS 7.3イメージを使いました。追加で必要なパッケージは以下の通りです。
・LDAPクライアント
・openldap-clients
・nss-pam-ldapd
・Radiusクライアント
・pam_radius-1.4.0.tar.gz
・Radiusクライアントをビルドするための環境
・gcc
・pam-devel
◆LDAPクライアントの設定
まず、LDAPクライアントをインストールします。sudo yum install openldap-clients nss-pam-ldapd
次に/etc/passwdの代わりにLDAPサーバを使うようにOSを構成します。
sudo authconfig-tui
を叩くと設定画面が開くので[User Information]の[Use LDAP]にチェックを入れます。認証側は後からRadiusを構成するのでここでは何も触りません。
Nextを叩くと、LDAPサーバへの接続設定が出てきますので、ServerのURIとBaseDNを設定します。
ここでOKをクリックすると設定は完了しますが、先に書いたようにActive DirectoryをLDAPサーバとして利用する場合は匿名bindが使えないので、バインドユーザの設定を直接設定ファイルを編集して登録します。
対象のファイルは/etc/nslcd.confで、binddnとbindpwというパラメータがデフォルトではコメントアウトされているので外して、必要な値を設定します。
次に同じく/etc/nslcd.confへ属性マッピング設定を追加します。これは例えばuidNumberやgidNumber、homeDirectoryなどLinuxへログインするために必要な属性が当然Active Directoryにはないので、それぞれ必要な値をActive Directory上のどの属性からとってくるか、という設定です。また、取得してくるobjectClassのフィルタリングも指定をしておかないとActive Directory上のユーザを適切にとって来れないので、filterの設定もしておきます。
最低限必要なのは以下の設定です。
filter passwd (&(objectClass=user)(!(objectClass=computer)))
map passwd uid sAMAccountName
map passwd homeDirectory "/home/$sAMAccountName"
map passwd uidNumber employeeId
map passwd gidNumber "1000"
map passwd loginShell "/bin/bash"
※uidNumberはActive Directory上のemployeeId属性に対応する値をあらかじめ入れます。また、今回gidNumberは固定にしていますがこれもActive Directory上の別の属性とマッピングすることで制御することが可能です。
◆ホームディレクトリの自動作成設定(pamの設定)
これでログインするユーザの情報をActive Directoryからとってくることは出来るようになりますが、Linuxではログインする際にホームディレクトリが存在しないと怒られますので、ログイン時に自動的にホームディレクトリが作成されるようにpamの設定を行います。2つのファイルを編集する必要がありますので順番に。
まずは/etc/pam.d/password-authに以下の2行を追記します。
session optional pam_ldap.so
session optional pam_mkhomedir.so skel=/etc/skel umask=022
同じく、/etc/pam.d/system-auth-acにも以下の2行を追記します。(同じ内容です)
session optional pam_ldap.so
session optional pam_mkhomedir.so skel=/etc/skel umask=022
こんな感じになります。
◆Radiusクライアントの導入
いよいよ認証側の設定です。デフォルトでRadiusクライアントが入っていないので、freeradiusと一緒に配布されているpam_radiusを使います。
まずはダウンロードします。現在1.4.0が最新版の様です。
wget ftp://ftp.freeradius.org/pub/radius/pam_radius-1.4.0.tar.gz
解凍します。この辺りまでは一般ユーザで十分です。
tar -xzvf pam_radius-1.4.0.tar.gz
ここで、configureしてmakeしたいところなんですが、必要な開発パッケージが入っていない場合はgccとpam-develをインストールしておきます。
sudo yum install gcc
sudo yum install pam-devel
そして、ビルドします。
configure
make
すると、pam_radius_auth.soが出来上がるので、必要なディレクトリへコピーします。(64bit環境であれば/usr/lib64/security/)
sudo cp pam_radius_auth.so /usr/lib64/security/
◆Radiusクライアントの設定
これで導入は完了なので、次は設定です。必要なのは、
・認証にRadiusを使うための設定
・使用するRadiusサーバの設定
の2点です。
まずはRadiusを使って認証をするための設定です。
/etc/pam.d/password-authに以下の行を追記します。
auth sufficient pam_radius_auth.so use_first_pass
こんな感じで、authのブロックに挿入してあげてください。
次にRadiusサーバへの接続設定です。
/etc/raddb/serverというファイルを作り、その中にサーバのアドレスと共有シークレットを書き込むのですが、FreeRadiusを入れていない環境だと/etc/raddbディレクトリやファイルが存在しないので、ディレクトリとファイルは新規に作る必要があります。
こんな感じです。
sudo mkdir /etc/raddb
sudo vi /etc/raddb/server
serverファイルの中は非常にシンプルで、「サーバアドレス 共有シークレット タイムアウト(秒)」を記載するだけです。尚、この共有シークレットはRadiusサーバ(今回はAzure MFA Server)に設定する文字列と同じものを指定するので覚えておいてください。
ファイルは作成後、パーミッションを600に指定しておいてください。
sudo chmod 600 /etc/raddb/server
これでクライアント側は終わりです。
◆Azure MFA Serverの設定
いよいよAzure MFA ServerをRadiusサーバとして動かします。詳細なインストール手順やAzure MFA ServerがActive Directoryをレポジトリとして利用するための構成手順、ポータルの設定手順などは今回は省き、単純に構成済みのAzure MFA ServerにRadiusクライアントの設定を行う方法を紹介します。
Azure MFA Serverの管理コンソールを開き、RADIUS Authenticationを開きClientsタブで[Add]をクリックします。
するとRADIUSクライアントを登録する画面が出てくるので、以下を設定します。
IP Address : クライアントのIPアドレス(LinuxのIPアドレス)
Application name : 任意の名前
Shared Secret : 先にLinuxに設定した共有シークレットの値
Confirm shared secret : 確認用
Require Mutlti-Factor Authentication user match : ON
Enable fallback OATH token : ON(今回は使わないのでOFFでもよい)
これでAzure MFA Serverの設定もおしまいです。
◆SSH接続許可設定
これで認証自体は通るようになるはずですが、SSHサーバの認可設定が必要です。クローズな環境ではあまり気にしなくても良いとは思いますが、今回Azure VMでCentOSを構成しているので、認証に加えて接続出来るユーザをある程度制限しておこうと思います。以下のファイルへ接続しても良いユーザ名を明記しておきます。
/etc/ssh/sshd_config
ここにAllowUsersパラメータを指定します。
構文は「AllowUsers ユーザ名をスペース区切りで列挙」なので、以下のような感じになります。ちなみに間違えると誰もつなげなくなるので別のコンソールを一枚あげておいた上で設定する様にしましょう。
※後で使うユーザはtestuser05なのでこの行にtestuser05を追記することでログイン可能になります。
編集が完了したらsshdに設定ファイルをリロードします。
sudo systemctl reload sshd
設定に失敗していると本当に誰もSSH接続できなくなりますので、端末のクローズは全部動作確認が出来た上でしてください。
◆ユーザの準備
いよいよ動作確認と行きたいと所ですが、その前にユーザの準備です。先ほどLDAPクライアントの設定でActive Directory上のユーザの属性のマッピングを行ったと思うので、必要な属性(今回はuidNumber)をActive Directory上のユーザのemployeeIdに登録しておく必要があります。
employeeIdはデフォルトではユーザのプロパティからは見えないので、拡張表示設定をしたうえで、属性エディタを開き、値を直接セットします。
そして、最後に多要素認証設定です。
今回はアプリを使って認証する様に設定します。
Azure MFA Serverのユーザポータルへアクセスし、Active Directoryのユーザ名/パスワードでログインします。
初回アクセスだと、認証方法を選択する画面になるので、「モバイルアプリ」を選択し、「アクティブ化コードの生成」をクリックします。
するとQRコードが表示されるので、Authenticatorアプリケーションで読み込んでアカウントが登録されるのを確認して、「今すぐ認証」をクリックします。
上手くいけば秘密の質問への回答の登録などの画面に遷移しますが、ここは直接は関係ないので割愛します。適当に登録しておきます。
◆動作確認
ようやく動作確認です。今回はTeraTerm Proを使ってSSH接続をします。
アドレスを入れて接続をするとユーザ名とパスワードを入れるダイアログが出るので、先のActive Directory上のユーザIDとパスワードでログオンを試みます。
すると、Authenticatorアプリに承認要求が届くので確認を行います。
ここまでの設定が上手くいっていればちゃんとログインできるはずです。
この様に、Azure MFA ServerはRadiusなど一般的な認証サーバとして振舞うことが出来、かつ間に多要素認証を挟み込むことが出来るので、応用範囲はかなり広いと思います。例えばVPN装置などこれまでクライアント証明書や個別に管理されているID/パスワードで認証していたものが運用上の問題になったり、セキュリティ上の弱点になったりするケースもあったと思いますが、このような工夫を組み合わせることにより少しでも楽にセキュリティレベルを向上することが出来る可能性がありますので、検討してみてください。