mod_rewriteでのreverse proxyとRedirect動作
Apacheでreverse proxyをする常套手段はmod_proxy(http://httpd.apache.org/docs/2.2/mod/mod_proxy.html)のProxyPassとProxyPassReverseディレクティブをセットで使う方法です。
ProxyPassはシンプルな場合に特化したディレクティブなので、複雑なルールでreverse proxyをしたい場合はmod_rewriteの[P]オプションを使います。ちなみに、http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewriterule にあるように、mod_rewriteの[P]オプションは内部的には、mod_proxyを必要としています。
mod_rewriteは次のページの次の言葉がよく性格を表わしています。
http://httpd.apache.org/docs/2.2/rewrite/
The great thing about mod_rewrite is it gives you all the configurability and flexibility of Sendmail. The downside to mod_rewrite is that it gives you all the configurability and flexibility of Sendmail.
某サーバで動作しているapacheがmod_rewriteによるreverse proxy動作をしていました。しかし、バックエンド(=reverse proxyされた側)のWebサーバがRedirect動作をした時に問題がありました。reverse proxyサーバが、RedirectレスポンスのLocationヘッダを適切に書き換えていないためです。
今まで、漫然とProxyPassとProxyPassReverseはセット、という思い込みがありましたが、ProxyPassReverseはmod_rewriteのRewriteRuleの[P]オプションとセットでも使えることを知りました。
こういう確認は、手元で簡単な設定ファイルを用意することで、ローカルのapacheだけで簡単に行えます。
次のようなふたつの設定ファイルを用意して、動作確認を行いました。fooの部分は適当なホスト名に置換してください。
# backend server ServerRoot "/usr/local/apache22" Listen 8081 User daemon Group daemon ServerAdmin you@example.com ServerName foo:8081 ErrorLog "logs/error_log" LogLevel warn LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined CustomLog "logs/access_log" combined PidFile "logs/httpd.pid" Alias /y /home/inoue/.emacs.el Redirect /x http://foo:8081/y
# reverse proxy server ServerRoot "/usr/local/apache22" Listen 8082 User daemon Group daemon ServerAdmin you@example.com ServerName foo:8082 ErrorLog "logs/error_log-rev" LogLevel warn LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined CustomLog "logs/access_log-rev" combined PidFile "logs/httpd-rev.pid" <VirtualHost *> ServerName foo:8082 RewriteEngine On RewriteRule (.*) http://foo:8081$1 [P] ProxyPassReverse / http://foo:8081/ </VirtualHost>
バックエンドサーバは /y にアクセスされると、.emacs.elを返すようにしています。これは今回の検証にとって意味はありません。単に /y でアクセスされるファイルを用意するのが面倒だったので、.emacs.elを返すようにしただけです。Redirect動作がreverse proxy経由でも適切に動作するかを確認するために、/x へのアクセスを /y にRedirectする設定をしました。
reverse proxyサーバの方は、事実上すべてのアクセスをバックエンドにproxyしています。
http://foo:8082/x にアクセスすると、http://foo:8081/x とバックエンドにproxyされ、バックエンドがRedirectレスポンスを返します。この時のLocationヘッダの値は http://foo:8081/y です。この後の動作が、ProxyPassReverseディレクティブの有無で変わります。 ProxyPassReverseディレクティブが無いと、Locationヘッダがそのまま書き換わらずに通過するので、ブラウザは http://foo:8081/y のバックエンドに直接アクセスします。ProxyPassReverseディレクティブがあると、Locationヘッダの値が http://foo:8082/y に書き換わるので、Redirect後のリクエストもreverse proxyに来ます。
この動作例の場合、ブラウザからバックエンドサーバに直接アクセスできる環境なので、Redirect後にreverse proxyに来なくても動作します。しかし、ブラウザがバックエンドサーバに直接アクセスできない場合(reverse proxyだけがインターネットから見えて、バックエンドサーバが見えない場合)には問題が生じます。
- Category(s)
- カテゴリなし
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/inoue/rewrite-and-redirect/tbping