2012年9月17日月曜日

"SSL Termination"(ELB)でアプリ(EC2)がHTTPSのチェックを行えない場合

スズキです。

CDPネタです。今回の対象は「Multi Load Balancerパターン」です。



ELBの"SSL Termination"機能で、SSLの処理をEC2(Webサーバ)ではなく
ELBに行わせることができますが、それに伴い、このパターンの「注意点」に
ELBのSSL Termination機能を用いるとEC2側はHTTPでリクエストを
受けることになるのでアプリケーションでのHTTPS接続の判定が難しくなる。
といった記載があります。

直接EC2のWebサーバでSSLの設定をして、HTTPSでのアクセスを行う場合は
PHPの場合、下記の環境変数でHTTPSの接続かどうかチェックしている場合が
多いとお思います。(つまり$_SERVER["HTTPS"]があるかどうかでチェック)




しかし、これをELBの"SSL Termination"機能でSSLの処理をELB側で行うとHTTPSのアクセスは
ELBでHTTPになりEC2にはHTTPでアクセスされることになります。


この場合、当然、上記の環境変数(HTTPS)はセットされません。
そうなると、アプリケーション側のHTTPSのチェックもHTTPSではない
(HTTPで接続)と判断され、それを使っている機能の挙動が変わってしまいます。
(HTTPSへのリダイレクトループが多いです)

では、アップリケーションはHTTPSかどうかのチェックを行うすべが無いかというと
そうではなく、以前、下記で紹介した通り、ELBのはEC2にリクエストを渡すとき
ELBの"SSL Termination"を利用したときのHTTPヘッダ
次のような"X-Forwarded-Xxx"といったヘッダをつけてくれます。


ですので、PHPの場合は"$_SERVER["HTTP_X_FORWARDED_PROTO"]"の値が
"https"かどうか(HTTPの場合は"http")でチェックすればよいことになります。


とはいえ、アプリケーションを修正することができない場合も多々あると思います。
そのような場合は、下記のようにWebサーバ(Apache)の設定(httpd.conf)で
環境変数をセットしてしまう方法もあります。

SetEnvIf X-Forwarded-Proto https HTTPS=on

"X-Forwarded-Proto"が"https"の場合は、クライアントはHTTPSで
アクセスされているので、環境変数"HTTPS"を"on"としてセットしています。


この場合、ELB経由のHTTPSのアクセスでも上記のようにEC2側で
今まで同様、環境変数(HTTPS)が"on"にセットされるので、アプリケーションの
修正無しに対応できる可能性は高いと思います。
($_SERVER["HTTPS"]のみHTTPS接続のチェックをしている場合)

さらに、Webサーバの設定も変更できない、もしくは、上記の変更では対応できない
($_SERVER["HTTPS"]以外でHTTPSのチェックをしている)場合などもあると思います。

このような場合は、ELBでSSLの処理(SSL Termination)した後に、もう一度
HTTPS通信にして、EC2にリクエストすることも可能です。


当然、EC2のWebサーバでSSLの設定を行っておく必要があります。そして
この場合ELB経由でもEC2のWebサーバはHTTPSで接続されるので、直接EC2に
HTTPSでアクセスする場合とアプリケーションはHTTPSのチェックに対して
同様の挙動となるはずです。

ELBがEC2にリクエストを渡すときに、もう一度HTTPS通信にする方法は、
下記のようにELB作成時に容易にできます。

まずは"Load Balancer Protocol"を"HTTPS"にするだけでなく、
EC2への接続に関する"Instance Protocol"も"HTTPS"にします。


そして途中でEC2とのSSL処理に利用する証明書を設定する画面になります。



ここで設定するSSL証明書は、下記の設定ファイル(Apacheのhttpd.conf)などで
設定されている、EC2上のWebサーバで利用しているものと同じものを設定します。

SSLCertificateFile /etc/pki/tls/certs/localhost.crt

アプリの変更無しにインフラを調整してAWSを利用するノウハウがたまってきた...
--------
http://www.suz-lab.com

1 コメント:

匿名 さんのコメント...

「ELB SSL」でここにたどり着きました。
…が2013年2月12日現在以下が最新で「x-forwarded-foraws」は付かないようです。

ELBでのHTTPSは"X-FORWARDED-FOR"がつかない(AWS)

nginxだとhttpsをデフォルトにして会ったらhttpと判定するくらしか方法がなさそうです。
set $_scheme 'https';
if ( $http_x_forwarded_proto ) {set $_scheme $http_x_forwarded_proto;}

そしてremote_ipは取りようが無い…