Apache2.2でリモートアドレスベースでの制限 "または" SSLクライアント証明書による認証を行う
現行でリモートアドレスベースでのアクセス制限を行っているサーバがあるんだけど、新たにSSLクライアント証明書をインストールした端末にもアクセスを許可したいという話があった。ちょっとトリッキーだけどなんかうまくいったので記録。むしろ情報求む。
クライアントに証明書を要求する
まず、アクセス時にクライアントに証明書を要求するわけだけど、リモートアドレスベースで許可されている場合には証明書は不要なので、ここではSSLVerifyClient optionalを指定する。
## ## SSL Virtual Host Context ## <VirtualHost _default_:443> ... <Directory "/var/www/html_ssl"> Options -Indexes FollowSymLinks AllowOverride All </Directory> SSLVerifyClient optional SSLVerifyDepth 1 </VirtualHost>
今回はSSLVerifyClient optionalをバーチャルホストまたはサーバレベルで設定する必要がある。DirectoryやLocationの中ではダメ。
Allow設定に追加する
SSL認証が成功した場合、SSL_CLIENT_VERIFYというヘッダに"SUCCESS"という文字列が設定されるので、それで条件判定した結果をAllowに追加する。
order deny,allow Deny from all # IPアドレスベースでのAllowが並んでいる Allow from XXX.XXX.XX.XXX ... # SSL_CLIENT_VERIFYがSUCCESSの場合に認証済みとする ※これは動かない!! SetEnvIf SSL_CLIENT_VERIFY "^SUCCESS$" clcertified Allow from env=clcertified
と思いきやこれは動かない。デフォルトでSetEnvIfで使えるヘッダは標準的なHTTPヘッダに限られていて、SSL_CLIENT_VERIFYヘッダを参照することはできないようだ。
てことは他の方法で環境変数セットするしかない。が、いろいろやってみるがうまくいかない。
# RewriteRuleで環境変数にセットしてやる ※これは動かない!! RewriteEngine on RewriteCond %{SSL:SSL_CLIENT_VERIFY} "^SUCCESS$" RewriteRule .* - [E=clcertified:SUCCESS,L]
どうやら、Allow from env=で使えるのはSetEnvIfで設定した環境変数だけらしい(cf: 「Allow | Turboflash's Blog」。) が、RewriteRuleはSetEnvIfより後に評価されるので、RewriteRuleの処理結果をSetEnvIfに伝えることもできない。
困っていたら、RequestHeaderディレクティブにearlyというキーワードを発見した。これを使ってみる。
## ## SSL Virtual Host Context ## <VirtualHost _default_:443> ... SSLVerifyClient optional SSLVerifyDepth 1 RequestHeader set SSL_CLIENT_VERIFY_early "%{SSL_CLIENT_VERIFY}s" early </VirtualHost>
早期処理の設定はメインサーバかバーチャルホストコンテキストに書かないとダメらしい。
なんと、RequestHeader setでセットしたヘッダはSetEnvIfで使える!これで認証済みかどうかの判定をAllowディレクティブに伝えられる。
# IPアドレスベースでのAllowが並んでいる Allow from XXX.XXX.XX.XXX ... # SSL_CLIENT_VERIFY_earlyがSUCCESSの場合に認証済みとする SetEnvIf SSL_CLIENT_VERIFY_early "^SUCCESS$" clcertified Allow from env=clcertified
これでリモートアドレスベースで登録されているクライアントと、クライアント証明書がインストールされているクライアントからのアクセスを許可できた(一応。)
穴が無いかとかもう少し調べてみる。