2012年9月26日水曜日

ロードバランサー(ELB)経由でなくてもX-Forwarded-Forをつける

スズキです。

Webサーバをロードバランサー(ELB)経由にするときに、
Webサーバに設定されるリモートアドレスが、ユーザー(ブラウザ)のものから
ロードバランサーのものになってしまうことは有名な話だと思います。

その場合、ELBは(その他の多くのロードバランサーも)X-Forwarded-Forヘッダに、
ユーザー(ブラウザ)のIPアドレスを設定してくれるので、下記で紹介した方法などで
対応することが可能です。
ApacheでREMOTE_ADDRをELB経由でも...(CentOS)
そして(あまり無いとは思いますが)、ロードバランサー経由のWebサーバを
インターネットからの直接アクセスに戻す場合もあるかと思います。
(あるとしたらコスト削減や障害対応などでしょうか...)

もし、アプリケーションなどでX-Forwarded-Forヘッダを参照している場合、
当然、インターネットからの直接アクセスではX-Forwarded-Forヘッダは無いので、
この場合、アプリケーション側で問題が発生してしまうはずです。

アプリケーションを修正するのは、現実的では無い場合が多く、なんとか
Webサーバ(Apache)側で対応したいところです。

といっても単に、リモートアドレスと同じIPアドレスが設定された、
X-Forwarded-Forヘッダが設定されていれば、アプリケーション的にも
問題がなくなるはずです。

Apacheの場合は下記のように設定(httpd.conf)すれば、上記を実現することができます。
SetEnvIf X-Forwarded-For ".+" forwarded
RewriteEngine On
RewriteRule ^(.*) - [E=CLIENT_ADDR:%{REMOTE_ADDR},L]
RequestHeader set X-Forwarded-For "%{CLIENT_ADDR}e" env=!forwarded
※ロードバランサー(ELB)経由の場合は、そのままのX-Forwarded-Forを利用します。

実際に下記のPHPスクリプトで、ロードバランサー(ELB)経由と、
インターネットからの直接アクセスでの該当変数を確認すると、
<?php
print("REMOTE_ADDR="          . $_SERVER["REMOTE_ADDR"]);
print("forwarded="            . $_SERVER["forwarded"]);
print("CLIENT_ADDR="          . $_SERVER["CLIENT_ADDR"]);
print("HTTP_X_FORWARDED_FOR=" . $_SERVER["HTTP_X_FORWARDED_FOR"]);
?>
ロードバランサー(ELB)経由の場合は、X-Forwarded-Forが下記のように
ロードバランサーが設定したもののままとなり、


インターネットからの直接アクセスの場合は、X-Forwarded-Forに下記のように
リモートアドレスの値が設定されます。


SetEnvIfだけでできると思ったのに...
--------
http://www.suz-lab.com

0 コメント: