Reverse Proxyの後ろでApplication Serverを動かす際に、REMOTE_HOSTを本当のアクセス元に書き換えてくれる仕組みはいくつかありますが^1、Plackでは壇上氏の Plack::Middleware::ReverseProxy がそれにあたります。
^1 例えば mod_extract_forwarded http://www.openinfo.co.uk/apache/
PM::ReverseProxy のSYNOPSISでもそうなってますが、このような仕組みを使う場合、REMOTE_HOSTを指定するのが安全です。
builder {
enable_if { $_[0]->{REMOTE\_ADDR} eq '127.0.0.1' }
"Plack::Middleware::ReverseProxy";
$app;
};
拙作の Plack::Builder::Conditionals を使うと以下のように書けます。
use Plack::Builder;
use Plack::Builder::Conditionals;
builder {
enable match_if addr(['192.168.0.0/24','127.0.0.1']),
"Plack::Middleware::ReverseProxy";
$app
};
このようにREMOTE_HOSTを指定するのは、改ざんされたリクエストを防ぐためです。
PM::ReverseProxyの仕組みは以下の図のようになります。
ブラウザ(IPアドレス:v.x.y.z)からReverse Proxyに対してリクエストを行うと、Reverse Proxyは「X-Forwarded-For」ヘッダにREMOTE_ADDRを追加してApplication Serverにリクエストします。Application Serverでは当然REMOTE_ADDRがReverse Proxyの物(ここではlocalhost)になりますが、PM::ReverseProxyはX-Forwarded-Forをみて、REMOTE_ADDRを上書きします。これにより本来のアクセス元がApplication ServerでもREMOTE_ADDRで取得できます。
ここで、Application Server側でREMOTE_ADDRを確認しないと、以下のような事態がおきます。
X-Forwarded-Forヘッダに任意のIPアドレス(v.x.y.z)を追加し、Application Serverに直接アクセスするとPM::ReverseProxyは同じようにREMOTE_ADDRを設定します。本来REMOTE_ADDRは「192.168.9.41」にも関わらず、「v.x.y.z」と名乗れてしまいます。もし、v.x.y.zからしか閲覧することができないコンテンツがあっても、この方法で見る事ができてしまいます。
use Plack::Builder;
use Plack::Builder::Conditionals;
builder {
enable 'ReverseProxy';
mount '/private' => builder {
enable match_if addr('!','v.x.y.z'),
sub { sub { [403,['Content-Type'=>'text/plain'],['Forbidden']] } };
$private_app;
};
$app
};
↑こういうの危険。
Application Serverに直接アクセスできないのは普通だと思いますが、なんらかの設定漏れでアクセスができてしまうことも考えられます。念をいれてREMOTE_ADDRをチェックするのをお勧めします。