WebOS Goodies

WebOS の未来を模索する、ゲームプログラマあがりの Web 開発者のブログ。

WebOS Goodies へようこそ! WebOS はインターネットの未来形。あらゆる Web サイトが繋がり、共有し、協力して創り上げる、ひとつの巨大な情報システムです。そこでは、あらゆる情報がネットワーク上に蓄積され、我々はいつでも、どこからでも、多彩なデバイスを使ってそれらにアクセスできます。 WebOS Goodies は、さまざまな情報提供やツール開発を通して、そんな世界の実現に少しでも貢献するべく活動していきます。
Subscribe       

Apache のリバースプロキシの設定方法

本日は Google Gears 関連のもうひとつのネタを書こうと思ったのですが、間に合わなかったので最近仕事で使った Apache のリバースプロキシ機能の設定方法などをご紹介します。リバースプロキシは、特定のディレクトリ以下へのリクエストを他の Web サーバーに中継する機能です。 LAN 内の複数のマシンで稼動している Web サイトをひとつのグローバル IP で公開したり、 Apache 以外の Web サーバー(Rails でよく使われる mongrel とか)を Apache の Web サイトに統合したりとかが簡単にできます。

Web サイトを柔軟に構築するために、覚えておくと便利ですよ。

前提条件

Apache のリバースプロキシ機能を利用するためには、 mod_proxy を組み込んだ Apache が必要です。通常の Linux ディストリビューションなどではデフォルトで有効になっていますので、たいていは問題ないと思います。

基本的な設定

Apache の mod_proxy 関連の設定方法は公式ドキュメントにあります。けっこうたくさんのディレクティブがありますが、この中でリバースプロキシに使うのは ProxyPass, ProxyPassReverse, ProxyPassReverseCookieDomain, ProxyPassReverseCookiePass の 4 つだけです。それぞれ個別にご紹介していきます。

ProxyPass

リクエスト URL のマッピングを指定するディレクティブです。これを指定しないとはじまりません。書式は以下のとおりです。

ProxyPass 公開パス 転送先URL

例として "proxy/" 以下へのリクエストを "http://www.example2.com/" に転送する設定は以下のようになります。

ProxyPass /proxy http://www.example2.com

例えば Apache サーバーの URL が "http://www.example1.com/" の場合、 "http://www.example1.com/proxy/foo.html" へのリクエストは "http://www.example2.com/foo.html" に転送されます。 Apache 2.1 からはコネクションプール関連のオプションが多数追加されましたが、それらの詳細は公式ドキュメントを参照してください。

ProxyPassReverse

HTTP レスポンスの Location, Content-Location, URI-header を書き換えるためのディレクティブです。主にリダイレクト先 URL を正しくマッピングするために使用されます。書式は ProxyPass とまったく同じです。

ProxyPassReverse 公開パス 転送先URL

ProxyPass の例と同じ条件なら以下のようになります。

ProxyPassReverse /proxy http://www.example2.com

こうすると、 "http://www.example2.com/bar.cgi" が "http://www.example2.com/foo.html" へのリダイレクトを返した場合に、リダイレクト先が "http://www.example1.com/proxy/foo.html" に書き換えられます。ただし、書き換えに使うドメイン名は UseCanonicalName ディレクティブの設定に影響されるので注意してください。

ProxyPassReverseCookieDomain

こちらは、 Set-Cookie ヘッダのドメインを書き換えるためのディレクティブです。ドメインを明示して Cookie を作成している場合などに必要になります。書式は以下のとおりです。

ProxyPassReverseCookieDomain 書き換え前のドメイン 書き換え後のドメイン

例えば、 "www.example2.com" への Set-Cookie を "www.example1.com" にマップしたい場合、以下のように指定します。

ProxyPassReverseCookieDomain www.example2.com www.example1.com

ドメインの並び順が ProxyPass とは逆になるので注意してください。もっとも、 Set-Cookie のドメイン指定は省略することが多いので、その場合はこのディレクティブを記述する必要はありません。

ProxyPassReverseCookiePath

ProxyPassReverseCookieDomain と同様に、 Set-Cookie のパスを書き換えるためのディレクティブです。書式もほぼ同じです。

ProxyPassReverseCookiePath 書き換え前のパス 書き換え後のパス

例えば、 "/" (ルート)への Cookie を "/proxy/" にマップする場合は以下のようになります。

ProxyPassReverseCookiePath / /proxy/

パス限定の Cookie はドメイン指定よりさらにレアケースなので、たいていは必要ないと思います。

注意点

非常に便利なリバースプロキシ機能ですが、いくつか注意すべき点もあるようです。とりあえず私が気付のは以下の 3 点。

  • 転送先URLのスキームは "http" のみです。つまり、転送先と SSL 通信を行うことはできません。 SSLProxyEngine というものを使えばできるそうです。コメント欄で教えてくださった ura さん、ありがとうございます!
  • ProxyPass ディレクティブによるマッピングは単純な前方一致しか指定できません。代わりに RewriteRule ディレクティブを使うことで、より複雑な指定も可能です。
  • HTML 中のリンクなどは補正されません。相対パスを使うなどの工夫が必要です。

SSL 通信ができないのはちょっと残念ですね。素人考えでは特に問題ないような気がするんですが、なにか理由があるんでしょうか。証明書が正しくないときの対処とかかな。

設定例

最後にいくつか代表的な設定を挙げておきます。

単純なマッピング

まずはディレクティブの説明で使った例をまとめておきます。 "http://www.example1.com/proxy/" 以下を "http://www.example2.com/" にマッピングします。

ProxyPass /proxy http://www.example2.com
ProxyPassReverse /proxy http://www.example2.com
ProxyPassReverseCookieDomain www.example2.com www.example1.com
ProxyPassReverseCookiePath / /proxy/

バーチャルホストを他の Web サーバーにマッピング

次は、バーチャルホストを他の Web サーバーに中継する例です。 "http://www.example1.com/" を "http://localhost:8080/" に、 "http://www.example2.com/" を "http://localhost:8081/" に、それぞれ転送します。

<VirtualHost *:80>
    ServerName www.example1.com
    ProxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/
    # その他の設定...
</VirtualHost>

<VirtualHost *:80>
    ServerName www.example2.com
    ProxyPass / http://localhost:8081/
    ProxyPassReverse / http://localhost:8081/
    # その他の設定...
</VirtualHost></pre>

Location ディレクティブ内に記述

Location セクションに ProxyPassProxyPassReverse を記述する場合は、公開パスの指定を省略します。 Location セクションで指定されたパスがそのまま適用されるためです。マッピングと同時にアクセス制限をかけたりするのに便利です。 ProxyPassReverseCookieDomainProxyPassReverseCookiePath は引数を省略できないので注意してください。

<Location "/proxy">
    ProxyPass http://www.example2.com
    ProxyPassReverse http://www.example2.com
    ProxyPassReverseCookieDomain www.example2.com www.example1.com
    ProxyPassReverseCookiePath / /proxy/
    AuthType Basic
    AuthName "Only for administrators"
    AuthUserFile /usr/local/apache/passwd/passwords
    Require user admin
</Location>

Rails をサブディレクトリで公開

応用として、 Rails で作成した Web アプリケーションを Web サイトのサブディレクトリ以下で公開する例を挙げておきます。 Apache のサイトの "/rails/" 以下に mongrel で起動した Rails アプリケーションをマッピングすることにします。

ProxyPass /rails http://localhost:3000/rails
ProxyPassReverse /rails http://localhost:3000/rails

転送先URL公開パスと同じパスを付けてやるのがポイントです。さらに mongrel の起動時に "&ndash;prefix 公開パス" というオプションをつけて、公開パスを mongrel に教えてやります。

mongrel_rails start -d -p 3000 --prefix /rails

こうすると link_to などが出力するリンク先パスの先頭に "/rails" が付加されるようになり、リンクが正しく機能します。当然ながらヘルパーを使わずに直書きしたパスは補正されないので、相対パスを使うなどして対処してください。

このとき、 SSL 経由でのアクセスも同様に転送する設定を行えば、 SSL をサポートしていない mongrel のサイトを SSL でラップすることができます。ただし、 Rails アプリケーションでリダイレクトを使っている場合には、注意が必要です。 Apache はリダイレクト先のプロトコル部分を書き換えてくれないようで、そのままではリダイレクトした途端に http に戻されてしまいます。これを回避するには、以下のようにしてリクエストヘッダに "X_FORWARDED_PROTO" を追加すると良いようです。

<VirtualHost *:443>
    # SSL の細かい設定(^^;
    RequestHeader set X_FORWARDED_PROTO 'https'
    ProxyPass /rails http://localhost:3000/rails
    ProxyPassReverse /rails http://localhost:3000/rails
</VirtualHost>

このヘッダの効果はきちんと調査していないのですが、こうすると mongrel がリダイレクト先として https://〜 の URL を返すようになり、リダイレクトが正しく行われるようです。

以上、本日は Apache のリバースプロキシの使い方をご紹介しました。複数の Web サーバーをひとつのサイトにまとめたり、暗号化されていない通信を Apache の SSL でラップするなど、いろいろ応用が考えられますね。さらに高度な指定をすればロードバランサにもなるようです。とても便利な機能だと思いますので、ぜひ活用してください!

関連記事

この記事にコメントする

Recommendations
Books
「Closure Library」の入門書です。
詳しくはこちらの記事をどうぞ!
Categories
Recent Articles