Apache 2.2 から実装されたプロキシバランサを、左図のような構図で使うことを想定する。リバースプロキシはユーザ(インターネット) からの全ての http リクエスト と https リクエストをロードバランスして実サーバ 1, 2 へ振り分ける。 https の場合は、リバースプロキシがリクエスト内容の暗号化をほどいてから実サーバ (バックエンドサーバ) に HTTPリクエストを送る。つまり SSLキーはリバースプロキシにだけ置いておけばいい。
このやりかたでは、実サーバのドキュメント空間をリバースプロキシのローカルドキュメント空間に割り付ける (概念的には alias に近い) イメージになるので、帰りのトラフィックもリバースプロキシを通る。 SSL通信の場合、実サーバからリバースプロキシへは平文でレスポンスが返され、リバースプロキシがそれを暗号化してからリクエストユーザへ返す。その点から、SSLを使う場合のプロキシサーバの仕事量は比較的重く、どちらかといえば実サーバよりもリバースプロキシのほうに立派なハードウェアを与えてやりたい。
2台の実サーバとも、各々の Apache上の ServerName には、インターネットユーザが解決可能な同一のサーバ名を設定する。もちろん、マシンとしてのホスト名は内部ネットワーク内で解決できるものでさえあればよく、例では real1.hoge.local, real2.hoge.local としている。
設定方法は、設定例のかたちで示すことにしよう。
Apacheプロキシバランサか Squid か動的なコンテンツ (CGIなど) があるかどうかによって、どちらが適しているかは違ってくる。静的なコンテンツばかりなら、コンテンツキャッシュができるという点で Squid に優位性があるだろう。かたや、動的コンテンツがある場合には、リクエストURI に含まれるパラメータによってセッションを加味した振り分けができる Apache のプロキシバランサが優位だ。あるいは Pound という選択肢もあるようだが、Pound については筆者は未研究。 Apacheプロキシバランサと Pound はコンテンツキャッシュはできない。(もう少し正確に言うと、 Apache をプロキシバランサとして使った場合、プロキシバランサマシン自体の所持しているコンテンツはキャッシュすることも可能だが、実サーバから取ってくるコンテンツはプロキシバランサでキャッシュすることができない)。また、どうせキャッシュができないのならと割り切った上で、発想をリバースプロキシから Linuxルータに転換し、Ultra Monkey でロードバランスを行うという選択肢もある。 |
# 前略 # Dynamic Shared Object (DSO) Support # このサーバはリバースプロキシ専用なので、ほとんどのモジュールは要らない。 # 以下はプロキシバランサとして必須のものだけで、これ以外にも基本モジュールが要る。 # # キャッシュは本当は働かないので実際は不要 LoadModule cache_module /usr/lib/httpd/modules/mod_cache.so # キャッシュは本当は働かないので実際は不要 LoadModule mem_cache_module /usr/lib/httpd/modules/mod_mem_cache.so LoadModule include_module /usr/lib/httpd/modules/mod_include.so LoadModule headers_module /usr/lib/httpd/modules/mod_headers.so LoadModule proxy_module /usr/lib/httpd/modules/mod_proxy.so LoadModule proxy_http_module /usr/lib/httpd/modules/mod_proxy_http.so LoadModule proxy_balancer_module /usr/lib/httpd/modules/mod_proxy_balancer.so LoadModule status_module /usr/lib/httpd/modules/mod_status.so # ロードしておいた方がよさそう LoadModule dir_module /usr/lib/httpd/modules/mod_dir.so LoadModule rewrite_module /usr/lib/httpd/modules/mod_rewrite.so # ここでSSL設定ファイル以外を読み込む。conf.d/ssl.conf は conf-ssl にリネームしておく Include conf.d/*.conf ## 中略 # # 通常のサーバ設定類がここに入る。 # ## # ここからがロードバランサ設定の核心 <IfModule mod_proxy.c> # `ProxyVia On' や `AllowCONNECT 443' をやってはいけない。 # ProxyRequests は必ず off に。 ProxyRequests off RewriteEngine On # バランサマネージャインターフェイスを使えるようにする <Location /balancer-manager> SetHandler balancer-manager Order allow,deny Allow From 127.0.0.1 </Location> # 実サーバへ転送しないURI。 ProxyPass /manual/ ! ProxyPass /server-status ! ProxyPass /server-info ! ProxyPass /balancer-manager ! # `/' つまり全てのリクエストURIをバランサ仮想ワーカーにアサインする。 # stickysession パラメータを指定すれば `...hoge.php?mysessid=xxx' # といったリクエストの xxx を加味して振り分け先実サーバが決定されるので、 # 一続きのCGIセッションが別の実サーバに振り分けられてしまうことがない。 ProxyPass / balancer://clusterflat/ \ timeout=5 stickysession=mysessid nofailover=On # リバースプロキシとしての基本設定。Apache Doc の `mod_proxy' 参照 ProxyPassReverse / http://real1.hoge.local/ ProxyPassReverse / http://real2.hoge.local/ # 負荷分散実サーバの指定。timeout はこちらでも設定した方がよい。 # route パラメータで指定した文字列(ここでは実サーバのIPの第4オクテット) # は、stackysession で指定したURIパラメータに付加されてから実サーバへ # 転送される。下記 `実サーバ 1' で言えば `...hoge.php?mysessid=xxx.14' # というURIに合成されてから実サーバへ送られる。 <Proxy balancer://clusterflat/> # 実サーバ 1 BalancerMember http://real1.hoge.local \ loadfactor=50 timeout=5 keepalive=on route=14 # 実サーバ 2 BalancerMember http://real2.hoge.local \ loadfactor=50 timeout=5 keepalive=on route=15 </Proxy> # 実サーバのCGI処理でSSLか非SSLか判定したい場合のディレクティブ。 # X-SSL-REQ ヘッダ (ヘッダ名は自由) には、リクエストスキームが https:// # だった場合には `1'、そうでない場合には `0' がセットされて実サーバへ # 転送される。 RequestHeader set X-SSL-REQ %{HTTPS}s # コンテンツキャッシュ設定。やってみたが無駄だった。プロキシサーバ上にある # コンテンツは確かにキャッシュされたが、実サーバから得たコンテンツは # キャッシュされなかった。 <IfModule mod_mem_cache.c> CacheEnable mem / CacheIgnoreHeaders Set-Cookie MCacheSize 40960 </IfModule> # プロキシが実サーバへコンテンツを取りに行く時、問題になるのが、ユーザからの # リクエストURIの最後にあるスラッシュ。プロキシから実サーバへの要求を確実に # 整形するには、下記の RewriteRule を使うのが最も有効だった。 RewriteRule ^/(.*)$ balancer://clusterflat/$1 [P] </IfModule> # ここで SSL設定ファイルをインクルードする Include conf.d/conf-ssl ### Section 3: Virtual Hosts # <VirtualHost _default_:80> ServerName www.hoge.com:80 LogLevel warn # ユーザからのリクエストヘッダにあるHOSTヘッダは実サーバへそのまま伝える。 # ネームベースのバーチャルホストを使っている場合には必須。 ProxyPreserveHost On ## このプロキシサーバと実サーバとの通信もSSL化したい場合(通常はそうする必要なし) ## には、以下をアンコメントする。同時に、SSL設定ファイル内の同様の部分もアンコメ ## ントし、メインブロックの `<IfModule mod_proxy.c>..</IfModule>' 内の同様の部分 ## はコメントアウトする。 #ProxyPass / balancer://clusterflat/ \ # timeout=5 stickysession=mysessid nofailover=On # #ProxyPassReverse / http://real1.hoge.local/ #ProxyPassReverse / http://real2.hoge.local/ # #<Proxy balancer://clusterflat/> # BalancerMember http://real1.hoge.local \ # loadfactor=50 timeout=5 keepalive=on route=14 # BalancerMember http://real2.hoge.local \ # loadfactor=50 timeout=5 keepalive=on route=15 #</Proxy> # #RewriteRule ^/(.*)$ balancer://clusterflat/$1 [P] </VirtualHost>
LoadModule ssl_module /usr/lib/httpd/modules/mod_ssl.so ## 中略 # # 通常のSSL設定類がここに入る # ## <VirtualHost *:443> ServerName www.hoge.com:443 LogLevel warn ## 中略 # # 通常の設定類がここに入る # ## # ユーザからのリクエストヘッダにあるHOSTヘッダは実サーバへそのまま伝える。 # ネームベースのバーチャルホストを使っている場合には必須。 ProxyPreserveHost On ## このプロキシサーバと実サーバとの通信もSSL化したい場合(通常はそうする必要はない) ## には、以下をアンコメントする。同時に、メイン設定ファイル内の同様の部分もアンコ ## メントし、メインブロックの `<IfModule mod_proxy.c>..</IfModule>' 内の同様の部分 ## はコメントアウトする。詳しい解説はメイン設定ファイルの方を参照のこと。 #ProxyPass / balancer://clusterssl/ \ # timeout=5 stickysession=mysessid nofailover=On # #ProxyPassReverse / https://real1.hoge.local/ #ProxyPassReverse / https://real2.hoge.local/ # #<Proxy balancer://clusterssl/> # # 実サーバ 1 # BalancerMember https://real1.hoge.local:443 \ # loadfactor=50 timeout=5 keepalive=on route=14 # # 実サーバ 2 # BalancerMember https://real2.hoge.local:443 \ # loadfactor=50 timeout=5 keepalive=on route=15 #</Proxy> # #RewriteRule ^/(.*)$ balancer://clusterssl/$1 [P] </VirtualHost>
不要なモジュールをロードから外すための参考となるよう、各モジュールの役割を一覧にした。通常最低限必要と思われるモジュールはセルをブルーにした。デフォルトの httpd.conf でいかにたくさんの無用なモジュールがロードされているかが分かる。もちろんサーバの運用方法によって事情は全く異なるので、設定ファイル内で実際に使っているディレクティブを確認しながら慎重に絞り込まなければならない。必要なものまで削ってしまうと、かえってセキュリティや安定性を落とすおそれもある。なお、Apache 2.2 で構成の変わったアクセス制御関係のモジュールはまだ網羅していない。
mod_ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
以下で指すユーザディレクトリは、 UserDir ディレクティブによる開放の場合だけでなく、 alias ディレクティブなどで開放する DocumentRoot 外のディレクトリも同様。Apache が当該のディレクトリにアクセスできるようにするには、ルートフォルダ / から当該のディレクトリに至る途中のディレクトリも、少なくとも実行ビットが立っていなくてはならない。パーミションそのものに関する考察はこちら。 Apache はユーザ apache、グループ apache で動かしているものとする。