mod_proxy: ProxyPass

2025-05-26

リバースプロキシとは何か?

まず、リバースプロキシの概念を理解することが重要です。

  • リバースプロキシ (Reverse Proxy)
    クライアント(ユーザー)はリバースプロキシサーバーにアクセスしますが、実際のリクエストはリバースプロキシサーバーが内部の別のサーバー(バックエンドサーバー、オリジンサーバーとも呼ばれます)に転送し、その結果をクライアントに返します。クライアントからは、あたかもリバースプロキシサーバーがコンテンツを直接提供しているかのように見えます。
  • フォワードプロキシ (Forward Proxy)
    クライアント(ユーザー)が直接アクセスできない外部のインターネットリソースにアクセスするために使用されます。クライアントはプロキシサーバーを経由して外部に接続します。

mod_proxyとは?

mod_proxyは、Apache HTTP Serverがプロキシ機能を提供するための主要なモジュールです。これ単体では基本的なプロキシ機能しか提供しませんが、mod_proxy_http(HTTPプロキシ用)、mod_proxy_ajp(Tomcatなどとの連携用)、mod_proxy_balancer(ロードバランシング用)といった関連モジュールと組み合わせて使用することで、より高度な機能を実現します。

ProxyPassディレクティブの役割

ProxyPassディレクティブは、Apacheをリバースプロキシとして機能させるために使用されます。具体的には、あるURLパスへのリクエストを、別のサーバー(バックエンドサーバー)の指定されたURLに転送する設定を行います。

構文例

ProxyPass "/path" "http://backend-server.example.com/otherpath"

この設定の意味

  1. /path: Apacheが受け取るリクエストのURLパスです。例えば、ユーザーがhttp://your-apache-server.com/path/somethingにアクセスした場合、この設定が適用されます。
  2. http://backend-server.example.com/otherpath: リクエストが実際に転送されるバックエンドサーバーのURLです。

具体的な動作

上記の例の場合、Apacheは以下のように動作します。

  • バックエンドサーバーからの応答を受け取ったApacheは、その応答をあたかも自分が生成したかのようにユーザーに返します。
  • バックエンドサーバーにリクエストを送信します。
  • Apacheは内部的にそのリクエストをhttp://backend-server.example.com/otherpath/fooに変換し、
  • ユーザーがhttp://your-apache-server.com/path/fooにアクセスすると、

ProxyPassReverseとの組み合わせ

ProxyPassとセットでよく使われるのがProxyPassReverseディレクティブです。

ProxyPass "/path" "http://backend-server.example.com/otherpath"
ProxyPassReverse "/path" "http://backend-server.example.com/otherpath"

ProxyPassReverseは、バックエンドサーバーからのレスポンスに含まれるリダイレクトヘッダー(Location:ヘッダーなど)を書き換えるために使用されます。

なぜProxyPassReverseが必要なのか?

バックエンドサーバーがリダイレクトを返す場合、そのリダイレクトURLはバックエンドサーバー自身のURL(例: http://backend-server.example.com/newlocation)になります。しかし、クライアントはリバースプロキシサーバー(例: http://your-apache-server.com/)にアクセスしているため、そのままではクライアントはバックエンドサーバーのURLに直接アクセスしようとしてしまい、問題が発生します。

ProxyPassReverseは、このようなリダイレクトヘッダーを自動的にApacheのリバースプロキシのURL(例: http://your-apache-server.com/path/newlocation)に書き換えることで、クライアントが正しくリダイレクトされるようにします。

mod_proxyとProxyPassの利用例

  • SSL/TLS終端
    ApacheでSSL/TLSを終端し、バックエンドサーバーへの通信はHTTPで行うことで、バックエンドサーバーのSSL/TLS設定の手間を省くことができます。
  • セキュリティの向上
    バックエンドサーバーを直接インターネットに公開せず、Apacheを介することで、ファイアウォールの内側にバックエンドサーバーを配置し、セキュリティを強化できます。
  • URLの統合
    複数の異なるサーバーで提供されているコンテンツを、一つのドメインやURLパスの下に統合して提供することができます。
  • 負荷分散(ロードバランシング)
    複数のバックエンドサーバーがある場合、mod_proxy_balancerと組み合わせて使用することで、リクエストを複数のサーバーに分散させ、負荷を均等にすることができます。
  • アプリケーションサーバーの公開
    TomcatやNode.jsなどのアプリケーションサーバーは、通常、特定のポート(例: 8080)で動作します。Apacheをリバースプロキシとして設定することで、ポート80(HTTP)や443(HTTPS)でリクエストを受け取り、内部のアプリケーションサーバーに転送することができます。これにより、ユーザーはポート番号を意識せずにサービスにアクセスできます。
  • ProxyPassディレクティブの順序は重要です。より具体的な(長い)パスを先に記述しないと、意図しない設定が適用される可能性があります。
  • ProxyRequests Offを設定することをお勧めします。これはフォワードプロキシ機能で、意図しないアクセスを防ぐためです。リバースプロキシには不要です。
  • mod_proxyおよび関連モジュールをApacheの設定ファイル(httpd.confなど)で有効にする必要があります。


mod_proxy: ProxyPass に関連するよくあるエラーとトラブルシューティング

mod_proxyProxyPassを使用する際に発生する一般的なエラーと、その解決策について説明します。

モジュールが有効になっていない (Module not enabled)

エラーの症状
Apacheが起動しない、またはProxyPassディレクティブが認識されない。Apacheのエラーログに「Invalid command 'ProxyPass', perhaps misspelled or defined by a module not included in the server configuration」のようなメッセージが出力される。

原因
mod_proxyおよび関連するプロキシモジュール(例: mod_proxy_httpmod_proxy_ajpmod_proxy_balancerなど)がApacheの設定で有効になっていない。

トラブルシューティング

  1. モジュールの有効化
    • Linux (Debian/Ubuntu系): sudo a2enmod proxy proxy_http
    • Linux (RHEL/CentOS系): sudo yum install httpd-devel (通常、デフォルトで有効)または設定ファイルでLoadModuleディレクティブを確認。
    • httpd.confまたはconf.d内の設定ファイルで、以下のような行のコメントアウトを解除します。
      LoadModule proxy_module modules/mod_proxy.so
      LoadModule proxy_http_module modules/mod_proxy_http.so
      # 必要に応じて他のモジュールも有効化
      # LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
      # LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
      
  2. Apacheの再起動/再読み込み
    モジュールの有効化後、Apacheを再起動(sudo systemctl restart apache2 または sudo systemctl restart httpd)するか、設定を再読み込み(sudo systemctl reload apache2 または sudo systemctl reload httpd)します。

503 Service Unavailable (バックエンドへの接続失敗)

エラーの症状
ブラウザに「503 Service Unavailable」エラーが表示される。Apacheのエラーログに以下のようなメッセージが出力される。

  • [proxy_http:error] AH01114: HTTP: failed to make connection to backend: ...
  • [proxy:error] AH01114: HTTP: failed to make connection to backend: backend-server.example.com
  • [proxy:error] AH00959: ap_proxy_connect_backend disabling worker for (backend-server.example.com)
  • [proxy:error] AH00961: HTTPS: failed to enable ssl support for 127.0.0.1:8443 (127.0.0.1)
  • [proxy:error] AH00957: HTTP: attempt to connect to 127.0.0.1:8080 (127.0.0.1) failed

原因
ApacheがProxyPassで指定されたバックエンドサーバーに接続できない場合に発生します。これは様々な理由が考えられます。

  • バックエンドサーバーのIPアドレスやポート番号が間違っている。
  • ネットワークの問題(DNS解決失敗、ルーティング問題など)。
  • ファイアウォールがApacheとバックエンドサーバー間の通信をブロックしている。
  • バックエンドサーバーが指定されたポートでリッスンしていない。
  • バックエンドサーバーが起動していない。

トラブルシューティング

  1. バックエンドサーバーの稼働確認
    • バックエンドサーバーが起動しているか確認します。
    • バックエンドサーバーが指定されたポートでリッスンしているか確認します。(例: netstat -tulnp | grep 8080
  2. Firewallの確認
    • Apacheサーバーとバックエンドサーバー間のファイアウォール(iptables, firewalld, Windows Firewallなど)設定を確認し、必要なポート(例: 8080)が開いているか確認します。
    • telnet backend-server-ip 8080nc -vz backend-server-ip 8080 コマンドを使用して、Apacheサーバーからバックエンドサーバーへの接続性をテストします。
  3. ネットワーク接続の確認
    • ping backend-server.example.com で名前解決と基本的なネットワーク接続を確認します。
    • もしIPアドレスで指定している場合は、IPアドレスが正しいか確認します。
  4. ProxyPassディレクティブの記述ミス
    • URLのスペルミス、ポート番号の誤りがないか確認します。
    • 末尾のスラッシュの有無が問題になる場合があります。
      • ProxyPass /app/ http://backend/app/ のように、両方に末尾のスラッシュを付けるか、両方とも付けないかのどちらかに統一すると良いことが多いです。
  5. ProxyTimeoutの設定
    • バックエンドサーバーの応答が遅い場合、デフォルトのタイムアウト設定では不十分なことがあります。ProxyTimeoutディレクティブでタイムアウト値を増やしてみます。
      ProxyTimeout 300 # 300秒に設定 (デフォルトは60秒)
      
  6. Apacheのログレベルの引き上げ
    • LogLevel debug を設定すると、より詳細なプロキシ関連のデバッグ情報がエラーログに出力されます。問題を特定するのに役立ちます。

502 Bad Gateway (バックエンドからの無効な応答)

エラーの症状
ブラウザに「502 Bad Gateway」エラーが表示される。Apacheのエラーログに以下のようなメッセージが出力される。

  • [proxy:error] AH00992: Backend renderer read from backend failed
  • [proxy:error] AH00898: Error reading from remote server returned by /path
  • [proxy:error] AH01084: pass request body failed to 127.0.0.1:8080 (127.0.0.1)

原因
Apacheはバックエンドサーバーに接続できたものの、バックエンドサーバーからの応答が無効であるか、途中で接続が切断された場合に発生します。

  • ネットワークの中断。
  • バックエンドサーバーがタイムアウトし、Apacheに何も返さなかった。
  • バックエンドサーバーが不完全なHTTPヘッダーを返している。
  • バックエンドサーバーが内部エラーを発生させている。

トラブルシューティング

  1. バックエンドサーバーのログ確認
    • 最も重要なステップです。バックエンドサーバー自身のアプリケーションログやWebサーバーログを確認し、エラーが発生していないか確認します。バックエンドで処理エラーが発生している可能性が高いです。
  2. バックエンドサーバーへの直接アクセス
    • Apacheを介さず、バックエンドサーバーに直接アクセスして、正常に動作するか確認します。
  3. タイムアウトの設定
    • ProxyTimeoutを増やすことで、バックエンドサーバーが処理に時間がかかっている場合にエラーを防ぐことができます。
  4. KeepAliveの設定
    • SetEnv proxy-nokeepalive 1 を設定し、プロキシ接続でKeepAliveを無効にすることで、一部の断続的な502エラーが解決する場合があります。
    • または、ApacheのKeepAliveおよびMaxKeepAliveRequests設定と、バックエンドサーバーのKeepAlive設定を一致させることで改善する場合があります。
  5. 大きなファイル転送時の問題
    • 大きなファイル転送中に502エラーが発生する場合、ネットワークの安定性やタイムアウト設定(ProxyTimeout)を見直す必要があります。

404 Not Found (パスの不一致、またはバックエンドでの404)

エラーの症状
ブラウザに「404 Not Found」エラーが表示される。

原因

  • バックエンドサーバーが、転送されたURLに対して404を返している。
  • リクエストがProxyPassにマッチせず、ApacheのDocumentRootからファイルを探してしまい、見つからない。
  • ProxyPassのパス設定と、バックエンドサーバーが期待するパスが一致していない。

トラブルシューティング

  1. ProxyPassのパス確認
    • Apache側のパスと、バックエンド側のパスが正しくマッピングされているか確認します。 例:
      # Apacheで /app/ にアクセスした場合、バックエンドの /mywebapp/ に転送
      ProxyPass "/app/" "http://backend-server.example.com/mywebapp/"
      ProxyPassReverse "/app/" "http://backend-server.example.com/mywebapp/"
      
      この場合、http://your-apache.com/app/index.htmlhttp://backend-server.example.com/mywebapp/index.html に転送されます。パスの末尾のスラッシュの有無が重要です。
  2. ProxyPassディレクティブの順序
    • 複数のProxyPassディレクティブがある場合、より具体的なパス(長いパス)を先に記述する必要があります。短いパスが先にマッチしてしまうと、意図しない転送が行われます。
      # 誤った順序の例 ( /app/ が /app/foo/ より先にマッチしてしまう)
      ProxyPass "/app/" "http://backend1/"
      ProxyPass "/app/foo/" "http://backend2/"
      
      # 正しい順序の例
      ProxyPass "/app/foo/" "http://backend2/"
      ProxyPass "/app/" "http://backend1/"
      
  3. バックエンドサーバーの確認
    • Apacheから転送されたURLが、バックエンドサーバーで実際に存在するか、または処理されるべきパスか確認します。直接バックエンドサーバーにアクセスして、同じURLで404になるか試します。

リダイレクトがループする、または間違ったURLにリダイレクトされる

エラーの症状
ブラウザが無限リダイレクトループに陥るか、バックエンドサーバーの内部URLにリダイレクトされる。

原因
ProxyPassReverseディレクティブの設定が不足しているか、正しくない。バックエンドサーバーが返すLocation:ヘッダーなどのリダイレクトURLが、リバースプロキシの外部URLに書き換えられていないため。

トラブルシューティング

  1. ProxyPassReverseの確認
    • ProxyPassを使用している場合は、必ず対応するProxyPassReverseディレクティブも設定します。
    • ProxyPassProxyPassReverseのパスが一致しているか確認します。
      ProxyPass "/mywebapp/" "http://backend-server.example.com:8080/app/"
      ProxyPassReverse "/mywebapp/" "http://backend-server.example.com:8080/app/"
      
  2. バックエンドサーバーの設定
    • 一部のアプリケーションサーバー(Tomcatなど)では、リバースプロキシ環境での動作を正しく行わせるために、コネクタ設定でproxyNameproxyPortなどの属性を設定する必要がある場合があります。これにより、アプリケーションが生成するURLが正しいものになります。 例 (Tomcatのserver.xml):
      <Connector port="8080" protocol="HTTP/1.1"
                 connectionTimeout="20000"
                 redirectPort="8443"
                 proxyName="your-apache-server.com"
                 proxyPort="80" />
      
      HTTPSを使用している場合はproxyPort="443"を設定します。
  3. HTTPS終端時の問題
    • ApacheでSSL/TLSを終端し、バックエンドへの接続がHTTPの場合、バックエンドアプリケーションがHTTPSでアクセスされていると認識せず、HTTPでリダイレクトを生成することがあります。
    • ApacheでRequestHeader set X-Forwarded-Proto "https"を設定し、バックエンドにプロトコル情報を伝えることで解決できる場合があります。バックエンドアプリケーションがこのヘッダーを認識するように設定されている必要があります。

リクエストヘッダーの問題 (一部機能が動かない)

エラーの症状
リバースプロキシ経由でアクセスすると、ログインできない、セッションが維持されない、一部の機能が動作しないなど。

原因

  • Cookieのパスが正しくない。
  • リクエストヘッダー(Hostヘッダー、X-Forwarded-*ヘッダーなど)が正しくバックエンドに転送されていない、またはバックエンドがそれらを正しく処理できていない。

トラブルシューティング

  1. Hostヘッダーの転送
    • 通常は自動的に転送されますが、明示的にProxyPreserveHost Onを設定することで、クライアントから送られてきたHostヘッダーをそのままバックエンドに転送できます。これがmod_proxyの推奨される設定です。
      ProxyPreserveHost On
      
  2. X-Forwarded-*ヘッダー
    • クライアントのIPアドレスをバックエンドに伝えるにはX-Forwarded-For、元のプロトコルを伝えるにはX-Forwarded-Protoを使用します。
      RequestHeader set X-Forwarded-Proto "https" env=HTTPS
      RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s
      
    • これらのヘッダーをバックエンドアプリケーションが正しく解釈するように設定する必要があります。
  3. Cookieパスの書き換え
    • バックエンドアプリケーションが生成するCookieのパスが、リバースプロキシのURLパスと一致しない場合に問題が発生します。
    • ProxyPassReverseCookiePath ディレクティブを使用して、Cookieのパスを書き換えることができます。
      ProxyPassReverseCookiePath "/app/" "/mywebapp/"
      # バックエンドが /mywebapp/ で生成するCookieのパスを /app/ に書き換え
      
    • ProxyPassReverseCookieDomain も同様にドメインを書き換えることができます。

ファイルのアップロード/ダウンロードが失敗する

エラーの症状
大きなファイルのアップロードやダウンロードが途中で失敗する。

原因

  • ネットワークの問題。
  • バックエンドサーバー側のタイムアウト設定が不足している。
  • Apacheのタイムアウト設定が不足している。
  1. タイムアウトの調整
    • ProxyTimeoutを十分な値に設定します。
    • ApacheのTimeoutディレクティブも確認します。
    • バックエンドサーバー(PHPのmax_execution_timeupload_max_filesize、TomcatのconnectionTimeoutなど)のタイムアウト設定とファイルサイズ制限も確認します。
  2. ProxyPassのオプション
    • timeout=Xconnectiontimeout=YProxyPassディレクティブに追加することもできます。
      ProxyPass "/path/" "http://backend-server/" timeout=300 connectiontimeout=5
      
  1. ログの確認が最優先

    • Apacheのエラーログ (/var/log/apache2/error.log/var/log/httpd/error_log など)
    • Apacheのアクセスログ (/var/log/apache2/access.log/var/log/httpd/access_log など)
    • バックエンドサーバーのアプリケーションログ、Webサーバーログ
    • システムログ (journalctl -xe/var/log/messages など)
    • ログレベルの引き上げ
      LogLevel debug に設定すると、より詳細な情報が得られます。問題の再現後、すぐに元に戻すようにしてください。
  2. 設定ファイルの構文チェック

    • sudo apachectl configtest または sudo httpd -t コマンドで、設定ファイルの構文エラーがないか確認します。
  3. 段階的なテスト

    • ProxyPass設定を最小限にしてテストし、問題がどこにあるのかを切り分けます。
    • バックエンドサーバーに直接アクセスして、バックエンド自体に問題がないか確認します。
  4. ネットワークツールの活用

    • pingtelnetnc (netcat) を使用して、Apacheサーバーからバックエンドサーバーへの基本的なネットワーク接続を確認します。
    • curl -v http://your-apache-server.com/your-proxied-path のようにcurlコマンドに-vオプションを付けて、HTTPヘッダーの詳細を確認します。
  5. キャッシュのクリア

    • ブラウザのキャッシュや、場合によってはApacheがmod_cacheを使用している場合のキャッシュもクリアしてみます。


これらの設定は、Apacheの設定ファイル(通常はhttpd.conf、またはconf.d/sites-available/内のバーチャルホスト設定ファイル)に記述します。変更を適用するには、Apacheの再起動または設定の再読み込みが必要です。

基本的なリバースプロキシ設定

最もシンプルな設定で、特定のパスへのすべてのリクエストをバックエンドサーバーに転送します。

# mod_proxy と mod_proxy_http を有効にする必要があります
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

# ProxyRequests をオフにすることで、フォワードプロキシとしての動作を防ぎます
ProxyRequests Off

# クライアントのHostヘッダーをバックエンドに転送します
ProxyPreserveHost On

# /app/ へのリクエストを http://localhost:8080/ に転送
ProxyPass "/app/" "http://localhost:8080/"
# バックエンドからのリダイレクトURLを書き換える
ProxyPassReverse "/app/" "http://localhost:8080/"

解説

  • ProxyPassReverse "/app/" "http://localhost:8080/":
    • バックエンドサーバーがLocation: http://localhost:8080/loginのようなリダイレクトヘッダーを返した場合、Apacheがこれを傍受し、Location: http://your-apache-server.com/app/loginに書き換えてクライアントに返します。これにより、クライアントは正しいリバースプロキシのURLにリダイレクトされます。
  • ProxyPass "/app/" "http://localhost:8080/":
    • クライアントがhttp://your-apache-server.com/app/にアクセスすると、リクエストはhttp://localhost:8080/に転送されます。
    • 例えば、http://your-apache-server.com/app/index.htmlへのリクエストは、バックエンドのhttp://localhost:8080/index.htmlに転送されます。
    • パスの末尾のスラッシュ: ProxyPassの第1引数と第2引数の末尾のスラッシュの有無は重要です。
      • 両方にスラッシュがある場合 (/app/http://localhost:8080/): /app/foohttp://localhost:8080/foo に転送されます。
      • 両方にスラッシュがない場合 (/apphttp://localhost:8080): /app/foohttp://localhost:8080/foo に転送されます。
      • 一方にスラッシュがない場合、挙動が変わることがあります。混乱を避けるため、両方にスラッシュを付けるか、両方付けないかを統一するのが一般的です。
  • ProxyPreserveHost On: クライアントがApacheに送ったHostヘッダー(例: www.example.com)をそのままバックエンドサーバーに転送します。これにより、バックエンドサーバーが複数のバーチャルホストを扱っている場合でも、正しいホスト名でリクエストを受け取れます。
  • ProxyRequests Off: これが重要です。意図しないフォワードプロキシとしての利用を防ぎ、セキュリティを強化します。

ルートパス (/) をリバースプロキシする

Webサーバーのルートパス (/) へのすべてのリクエストをバックエンドに転送する設定です。Apacheが静的ファイルを全く提供せず、すべてバックエンドに任せる場合に有効です。

ProxyRequests Off
ProxyPreserveHost On

# ルートパスへのリクエストを http://localhost:8080/ に転送
ProxyPass "/" "http://localhost:8080/"
ProxyPassReverse "/" "http://localhost:8080/"

注意点
この設定を行うと、ApacheのDocumentRootに配置された静的ファイルにはアクセスできなくなります。もし静的ファイルをApacheが提供する必要がある場合は、より具体的なProxyPassディレクティブを先に記述する必要があります(例: /images/のようなパスはApacheが処理し、それ以外はバックエンドに転送するなど)。

特定のパスを除外する

一部のリクエスト(例: 静的ファイル)はApacheが直接処理し、それ以外のパスはバックエンドに転送したい場合に利用します。

ProxyRequests Off
ProxyPreserveHost On

# /images/ 以下へのリクエストはプロキシしない (Apacheが直接処理)
ProxyPass "/images/" "!"

# それ以外のすべてのリクエストを http://localhost:8080/ に転送
ProxyPass "/" "http://localhost:8080/"
ProxyPassReverse "/" "http://localhost:8080/"

解説

  • ディレクティブの順序が重要: より具体的なパス(この場合は/images/)のProxyPassディレクティブを、より一般的なパス(/)の前に記述する必要があります。Apacheは設定を上から順に評価し、最初にマッチしたディレクティブを適用します。
  • ProxyPass "/images/" "!": これは特別な記述で、「/images/で始まるパスへのリクエストはプロキシしない」という意味になります。

HTTPS終端とX-Forwardedヘッダー

ApacheでSSL/TLS通信を終端し、バックエンドサーバーには平文のHTTPでリクエストを転送する場合に非常に役立ちます。また、クライアントの元のIPアドレスやプロトコル情報をバックエンドに伝えるためのヘッダーも設定します。

# SSL/TLS設定 (VirtualHostのSSLEngine Onなど、別途設定済みと仮定)

ProxyRequests Off
ProxyPreserveHost On

# クライアントのIPアドレスをバックエンドに伝える
# バックエンドのアプリケーションがこのヘッダーを解釈できるように設定する必要がある
RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s

# クライアントがHTTPSでアクセスしたことをバックエンドに伝える
# バックエンドのアプリケーションがこのヘッダーを解釈できるように設定する必要がある
RequestHeader set X-Forwarded-Proto "https" env=HTTPS

# /app/ へのリクエストを http://localhost:8080/ に転送
ProxyPass "/app/" "http://localhost:8080/"
ProxyPassReverse "/app/" "http://localhost:8080/"

解説

  • RequestHeader set X-Forwarded-Proto "https" env=HTTPS:
    • リクエストヘッダーにX-Forwarded-Protoを追加し、そこにhttpsをセットします。
    • これは、クライアントがHTTPSでアクセスしてきた場合にのみ適用されます(env=HTTPS条件)。
    • バックエンドアプリケーションが、自分にはHTTPでリクエストが来ているにも関わらず、実際はHTTPSでアクセスされていることを認識し、リダイレクトやURL生成を適切に行えるようになります。
  • RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s:
    • リクエストヘッダーにX-Forwarded-Forを追加し、そこにクライアントのIPアドレスをセットします。
    • バックエンドサーバーのアクセスログにはApacheのIPアドレスではなく、クライアントの元のIPアドレスが記録されるようになります(バックエンドアプリケーションがこれを読み込む設定が必要です)。

ロードバランシング (複数のバックエンドサーバー)

mod_proxy_balancerモジュールと組み合わせて、複数のバックエンドサーバー間でリクエストを負荷分散させることができます。

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so

ProxyRequests Off
ProxyPreserveHost On

# バランサーの定義 (balancer://mycluster は任意の名前)
<Proxy balancer://mycluster>
    # メンバーノードの定義
    BalancerMember "http://backend1.example.com:8080"
    BalancerMember "http://backend2.example.com:8080"
    # バランシングアルゴリズム (デフォルトはbyrequests)
    # BalancerAlgorithm bytraffic
    # BalancerAlgorithm bybusyness
</Proxy>

# /app/ へのリクエストを定義したバランサーに転送
ProxyPass "/app/" "balancer://mycluster/"
ProxyPassReverse "/app/" "balancer://mycluster/"

# バランサーマネージャーへのアクセス (オプション: ロードバランサーの状態監視用)
<Location "/balancer-manager">
    SetHandler balancer-manager
    Order Deny,Allow
    Deny from all
    Allow from 127.0.0.1 # 特定のIPアドレスからのみアクセスを許可
</Location>

解説

  • /balancer-manager: これはオプションですが、ロードバランサーの現在の状態をWebブラウザで確認できる便利なインターフェースです。本番環境では、アクセスを制限するべきです。
  • ProxyPass "/app/" "balancer://mycluster/": /app/へのリクエストを、定義したmyclusterバランサーに転送します。
  • BalancerAlgorithm: 負荷分散のアルゴリズムを指定します(例: byrequests (デフォルト、リクエスト数)、bytraffic (トラフィック量)、bybusyness (現在の処理中のリクエスト数))。
  • BalancerMember: グループ内の各バックエンドサーバー(ノード)を定義します。
  • <Proxy balancer://mycluster>: balancer://スキームを使って、ロードバランシンググループを定義します。

AJP (Apache JServ Protocol) を使用したTomcatとの連携

TomcatのようなJavaアプリケーションサーバーと連携する場合、HTTPプロキシよりもAJPプロトコルを使用した方が効率的な場合があります。これにはmod_proxy_ajpが必要です。

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

ProxyRequests Off
ProxyPreserveHost On

# /app/ へのリクエストを ajp://localhost:8009/ に転送
# 8009 はTomcatのAJPコネクタのデフォルトポート
ProxyPass "/app/" "ajp://localhost:8009/app/"
ProxyPassReverse "/app/" "ajp://localhost:8009/app/"
  • ProxyPassReverseのパス: ここでも、ProxyPassの第2引数と一致させる必要があります。
  • ProxyPass "/app/" "ajp://localhost:8009/app/":
    • ajp://スキームを使用している点がHTTPプロキシとの違いです。
    • Tomcatのserver.xmlでAJPコネクタが有効になっている必要があります(通常、デフォルトで有効です)。
      <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
      


ここでは、Apache HTTP Server 内での代替方法と、Apache 以外の一般的なリバースプロキシソリューションについて説明します。

Apache HTTP Server 内での代替方法

mod_proxy 以外にも、Apache HTTP Server にはリクエストの転送や処理を行うための他のモジュールやディレクティブが存在します。

mod_rewrite の [P] フラグ

mod_rewrite はURLの書き換えに特化したモジュールですが、[P] (Proxy) フラグを使用することで、書き換えられたリクエストを mod_proxy に渡してプロキシさせることができます。これは ProxyPass ディレクティブよりも柔軟なURLマッピングが必要な場合に特に有効です。

特徴

  • RewriteCond と組み合わせて、リクエストヘッダー、環境変数、クライアントIPなど、様々な条件でプロキシを制御できる。
  • 特定の条件に基づいてプロキシ先を動的に決定できる。
  • 正規表現を使った高度なURLマッピングが可能。


/api/v1/ で始まるリクエストを backend-api.example.com に、/app/ で始まるリクエストを backend-app.example.com にプロキシし、さらに特定のクエリパラメータがある場合にのみプロキシする。

LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

RewriteEngine On
ProxyRequests Off
ProxyPreserveHost On

# /api/v1/ で始まるリクエストを特定のAPIサーバーにプロキシ
RewriteRule "^/api/v1/(.*)$" "http://backend-api.example.com/$1" [P,L]

# /app/ で始まるリクエストをアプリケーションサーバーにプロキシ
# ただし、特定のクエリパラメータ "debug=true" がある場合のみ
RewriteCond %{QUERY_STRING} debug=true
RewriteRule "^/app/(.*)$" "http://backend-app.example.com/$1" [P,L]

# ProxyPassReverse は RewriteRule とは直接関連しないが、
# バックエンドからのリダイレクトを処理するために別途必要
ProxyPassReverse "/api/v1/" "http://backend-api.example.com/api/v1/"
ProxyPassReverse "/app/" "http://backend-app.example.com/app/"

注意点

  • ProxyPassReverseRewriteRule によって生成されたプロキシには自動的に適用されないため、別途記述する必要があります。
  • RewriteRuleProxyPass は異なるメカニズムで動作するため、同じパスに対して両方を定義すると予期せぬ挙動になる可能性があります。通常は、RewriteRule を使う場合は ProxyPass は使わないか、衝突しないように慎重に設定します。

mod_headers などを使ったリクエスト/レスポンスヘッダーの操作

直接的なプロキシの代替というよりは、mod_proxy と組み合わせて使用されることが多いですが、mod_headers を使ってリクエストやレスポンスのヘッダーを細かく操作することで、バックエンドサーバーとの連携をよりスムーズにしたり、セキュリティを強化したりできます。


クライアントIPアドレスをバックエンドに伝えるために X-Forwarded-For ヘッダーを追加したり、セキュリティヘッダーを設定したりする。

LoadModule headers_module modules/mod_headers.so

# クライアントのIPアドレスをバックエンドに伝える (mod_proxy と組み合わせる)
RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s

# バックエンドからのレスポンスにセキュリティヘッダーを追加
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "DENY"

Apache HTTP Server 以外にも、リバースプロキシとして機能する専用のソフトウェアやツールが多数存在します。これらは、特定のユースケースにおいてApacheのmod_proxyよりも優れている場合があります。

Nginx

Nginx は、Webサーバーとしてだけでなく、高性能なリバースプロキシ、ロードバランサー、HTTPキャッシュとしても非常に人気があります。Apacheよりも軽量で、高負荷時のパフォーマンスに優れるとされています。

特徴

  • キャッシュ機能が組み込まれている。
  • WebSocketsのプロキシに優れている。
  • ロードバランシング機能が豊富。
  • シンプルな設定構文。
  • イベント駆動型アーキテクチャにより、同時接続数が多い環境で高いパフォーマンスを発揮。

設定例 (Nginx)

http {
    upstream backend_servers {
        server 127.0.0.1:8080;
        server 127.0.0.1:8081; # ロードバランシングの例
    }

    server {
        listen 80;
        server_name your-nginx-server.com;

        location /app/ {
            proxy_pass http://backend_servers/; # バックエンドのURIを維持
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme; # HTTP/HTTPSを伝える
            proxy_redirect default; # バックエンドからのリダイレクトを適切に書き換え
        }

        # WebSocketのプロキシ例
        location /ws/ {
            proxy_pass http://127.0.0.1:8082;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
        }

        # 特定のパスは静的ファイルとして提供
        location /static/ {
            root /var/www/html;
        }
    }
}

Apache mod_proxy との比較

  • SSL/TLSの終端処理もNginxは非常に得意です。
  • 複雑なURL書き換えが必要な場合はApacheのmod_rewriteが強力ですが、Nginxも正規表現ベースのlocationブロックで柔軟な設定が可能です。
  • Nginxは、特に静的コンテンツの配信とリバースプロキシの組み合わせで、Apacheよりも効率的な場合があります。

HAProxy

HAProxy は、高可用性、ロードバランシング、TCP/HTTPプロキシに特化したソリューションです。Webサーバー機能は持たず、プロキシ機能に徹することで、非常に高いパフォーマンスと信頼性を実現します。

特徴

  • 設定は比較的複雑になることがある。
  • TCPレベルのプロキシも可能(データベースプロキシなど)。
  • セッション維持 (Sticky Sessions) の機能が充実している。
  • 高度なロードバランシングアルゴリズムとヘルスチェック機能。
  • 非常に高速で、大量の同時接続とスループットを処理できる。

設定例 (HAProxy)

frontend http_front
    bind *:80
    mode http
    default_backend http_back

backend http_back
    mode http
    balance roundrobin # ロードバランシングアルゴリズム
    server backend1 192.168.1.10:8080 check # ヘルスチェック有効
    server backend2 192.168.1.11:8080 check

# HTTPS終端を行う場合
frontend https_front
    bind *:443 ssl crt /etc/haproxy/certs/yourdomain.pem
    mode http
    default_backend https_back

backend https_back
    mode http
    balance roundrobin
    server backend1 192.168.1.10:8080 check
    server backend2 192.168.1.11:8080 check

# 統計情報インターフェース (オプション)
listen stats
    bind *:8081
    stats enable
    stats uri /stats
    stats realm Haproxy\ Statistics
    stats auth admin:password

Apache mod_proxy との比較

  • 高トラフィック環境での純粋なロードバランシングやプロキシ性能を求めるならHAProxyが非常に強力です。
  • ApacheとHAProxyは、役割が明確に異なります。HAProxyはWebサーバー機能を持たないため、HAProxyをリバースプロキシとして使用し、その背後にApacheをWebサーバーとして配置する構成もよく見られます。

クラウドサービスのロードバランサー/API Gateway

AWS (Application Load Balancer / Network Load Balancer / API Gateway)、Google Cloud (Cloud Load Balancing / API Gateway)、Azure (Application Gateway / Azure Front Door) などのクラウドプロバイダーが提供するロードバランサーやAPI Gatewayサービスも、リバースプロキシと同様の機能を提供します。

特徴

  • 複雑なルーティングルールやAPI管理機能。
  • WAF (Web Application Firewall) やCDNとの統合が容易。
  • 自動スケーリング、高可用性、セキュリティ機能が組み込まれている。
  • フルマネージドサービスであり、インフラの管理が不要。
  • 設定は各クラウドプロバイダーのコンソールやCLI/APIで行います。
  • オンプレミス環境や限られたリソースでの構築ではApacheが適していますが、クラウドネイティブな環境ではマネージドサービスが運用コストやスケーラビリティの面で優位です。
  • Apache 以外のソリューション
    • Nginx: 軽量かつ高性能なリバースプロキシ/ロードバランサーとして非常に人気。静的ファイル配信とプロキシの組み合わせ、高同時接続数に強い。
    • HAProxy: 高性能なロードバランサー/TCP/HTTPプロキシに特化。非常に高いスループットと信頼性が求められる場合に最適。
    • クラウドサービスのロードバランサー/API Gateway: クラウド環境での運用に最適。マネージドサービスとして、スケーラビリティ、可用性、セキュリティ、運用負荷の低減に優れる。
  • Apache HTTP Server 内での代替
    • mod_rewrite[P] フラグ: ProxyPass よりも柔軟なURLマッピングや条件分岐が必要な場合に強力。
    • mod_headers: プロキシと組み合わせて、ヘッダー操作による機能拡張やセキュリティ強化。