Apache HTTP Serverでリバースプロキシを構築:mod_proxyとの設定例

2025-05-27

mod_proxy: <Proxy> とは?

mod_proxy は Apache HTTP Server のモジュールで、HTTP リクエストを別のサーバー(バックエンドサーバー)に転送する、つまり「プロキシ」として機能するための機能を提供します。このプロキシ機能の設定において、<Proxy> ディレクティブはプロキシの対象となる URL パスを定義し、そのパスに対するプロキシの挙動を制御するために使用されます。

簡単に言えば、Apache が特定のリクエストを受け取った際に、そのリクエストをどこに転送するか、どのように転送するかを設定するための「箱」のようなものです。

<Proxy> ディレクティブの構文

基本的な構文は以下のようになります。

<Proxy url-path>
    ... 設定ディレクティブ ...
</Proxy>
  • url-path: プロキシの対象となる URL のパスを指定します。これは、クライアントからのリクエスト URL のパス部分とマッチングされます。具体的には、プロトコル、ホスト、ポートを含まないパス部分です。

<Proxy> ディレクティブの主な用途と機能

<Proxy> ディレクティブ内では、以下のような様々な設定を行うことができます。

  1. プロキシ対象の定義: 最も基本的な機能です。例えば、/app/ というパスへのリクエストを別のサーバーに転送したい場合、以下のように記述します。

    <Proxy "http://backend-server.example.com/">
        # このバックエンドサーバーへのプロキシに関する設定
    </Proxy>
    

    この例では、http://backend-server.example.com/ がプロキシの対象となるバックエンドサーバーのベース URL です。

  2. プロキシのアクセス制御: 特定のクライアント IP アドレスからのプロキシアクセスを許可または拒否できます。これは <Directory><Location> と同様に、Require ディレクティブなどを用いて行います。

    <Proxy "http://backend-server.example.com/api/">
        Require ip 192.168.1.0/24
    </Proxy>
    

    この場合、192.168.1.x のネットワークからのアクセスのみが /api/ へのプロキシを許可されます。

  3. 環境変数の設定: プロキシされたリクエストに特定の環境変数を設定することができます。これはバックエンドサーバーが、プロキシ経由のリクエストであることを認識したり、追加情報を受け取ったりするのに役立ちます。

    <Proxy "http://backend-server.example.com/">
        SetEnv PROXY_VIA_APACHE 1
    </Proxy>
    
  4. ロードバランシング (mod_proxy_balancer): mod_proxy_balancer と組み合わせて使用することで、複数のバックエンドサーバー間でリクエストを分散させるロードバランシングの設定を行うことができます。この場合、<Proxy> 内に BalancerMember ディレクティブなどを記述します。

    <Proxy balancer://mycluster>
        BalancerMember http://server1.example.com:8080
        BalancerMember http://server2.example.com:8080
        ProxySet lbmethod=byrequests
    </Proxy>
    

    この例では、mycluster という名前のバランサーを定義し、2つのバックエンドサーバーにリクエストをラウンドロビンで分散します。

mod_proxy の設定において、<Location><LocationMatch> も同様に URL パスに基づいて設定を行うディレクティブですが、<Proxy> とは明確な違いがあります。

  • <Proxy>:

    • プロキシ先(バックエンドサーバー)のベース URL に対してマッチングを行います。
    • mod_proxy を介して転送されるリクエストの挙動(どこへ転送するか、アクセス制御、ロードバランシングなど)を制御します。
    • 特定のプロキシターゲットに対する設定をカプセル化するために使用されます。
  • <Location> / <LocationMatch>:

    • クライアントからのリクエスト URL のパスに対してマッチングを行います。
    • 主として、Apache サーバー自身が処理するリクエスト(静的ファイル、CGIスクリプトなど)に対するアクセス制御や設定を行います。
    • プロキシ先を定義するものではありません。

例えば、/app/ というパスへのリクエストをプロキシしたい場合、通常は ProxyPass ディレクティブと組み合わせて使用します。

ProxyPass /app/ http://backend-server.example.com/
<Proxy "http://backend-server.example.com/">
    # backend-server.example.com へのプロキシに関する設定
</Proxy>

この設定では、クライアントが /app/ にアクセスすると、それが http://backend-server.example.com/ に転送されます。そして、<Proxy "http://backend-server.example.com/"> ブロック内の設定は、この転送されるリクエスト(つまり、http://backend-server.example.com/ へのリクエスト)に適用されます。



mod_proxy: <Proxy> の一般的なエラーとトラブルシューティング

mod_proxy は非常に強力なモジュールですが、設定ミスやバックエンドサーバーの問題により、様々なエラーが発生することがあります。

モジュールがロードされていない (mod_proxy is not loaded)

エラーの症状:

  • ログファイルに Invalid command 'ProxyPass'Invalid command 'ProxySet' などのエラーが出力される。
  • Apache が起動しない、またはプロキシ設定が適用されない。

原因: mod_proxy および関連するサブモジュール(例: mod_proxy_http, mod_proxy_ajp, mod_proxy_balancer, mod_proxy_wstunnel など)が Apache の設定で有効化されていない。

トラブルシューティング:

  • Apache を再起動またはリロードします。
  • モジュールを有効化するコマンドを実行します(Debian/Ubuntu の場合)。
    sudo a2enmod proxy
    sudo a2enmod proxy_http
    sudo systemctl restart apache2
    
  • Apache の設定ファイル(通常 httpd.confconf-enabled ディレクトリ内のファイル)に以下の LoadModule ディレクティブが含まれているか確認します。必要に応じてコメントアウトを解除するか、追加します。
    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
    # LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
    # LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
    

プロキシ先への接続エラー(502 Bad Gateway / 503 Service Unavailable)

エラーの症状:

  • Apache の error_log に以下のようなメッセージが出力される。
    • proxy: error reading status line from remote server
    • proxy: AJP: failed to connect to backend host
    • (7007)The timeout specified has expired: proxy: error reading status line from remote server
    • Connection refused: proxy: AJP: attempt to connect to backend host failed
  • クライアントに「502 Bad Gateway」または「503 Service Unavailable」エラーが返される。

原因:

  • Apache とバックエンドサーバー間のKeep-Alive接続の問題。
  • バックエンドサーバーがタイムアウトしている。
  • ネットワークの問題(ファイアウォール、ルーティング、DNS解決など)。
  • バックエンドサーバーのIPアドレスやポートが間違っている。
  • バックエンドサーバーがダウンしている、または応答していない。

トラブルシューティング:

  • Keep-Alive接続の無効化:
    • まれに、Keep-Alive接続が原因で問題が発生することがあります。以下のディレクティブを試してみてください。
      SetEnv proxy-nokeepalive 1
      
      または、ProxyPassdisablereuse=on を追加します。
      ProxyPass /app/ http://backend-server.example.com/ disablereuse=on
      
  • タイムアウト設定の調整:
    • ProxyTimeout ディレクティブの値を増やしてみます。デフォルトは非常に短い場合があります。
      ProxyTimeout 300 # 300秒 (5分) に設定
      
  • ファイアウォールの確認:
    • Apache サーバーからバックエンドサーバーへの接続が、サーバーのOSレベルのファイアウォール(iptables/firewalldなど)やネットワーク機器のファイアウォールによってブロックされていないか確認します。
  • 設定の確認:
    • ProxyPass ディレクティブや <Proxy> ディレクティブで指定されているバックエンドサーバーのIPアドレス、ホスト名、ポート番号が正しいか再確認します。
    • スペルミスがないか、特にスラッシュ / の有無が重要です。ProxyPass /app/ http://backend-server.example.com/ のように、両方に末尾のスラッシュを付けるか、両方につけないか、一貫性を持たせるのが一般的です。
  • バックエンドサーバーの稼働確認:
    • バックエンドサーバーが実際に起動しているか確認します。
    • Apache サーバーから curltelnet コマンドでバックエンドサーバーにアクセスできるか確認します。
      # HTTPの場合
      curl -v http://backend-server.example.com:8080/
      # AJPの場合 (AJPポートは通常8009)
      telnet backend-server.example.com 8009
      

リダイレクトループ / 不適切なリダイレクト(301 Moved Permanently / 302 Found)

エラーの症状:

  • ブラウザのデベロッパーツールでHTTPステータスコードが3xx(301, 302, 307)で何度もリダイレクトされていることが確認できる。
  • クライアントがリダイレクトループに陥る、または意図しないURLにリダイレクトされる。

原因:

  • バックエンドサーバーが、プロキシ経由でアクセスされていることを認識せず、元のURLパスでリダイレクトを返してしまう。
  • ProxyPassReverse ディレクティブの設定漏れや誤り。

トラブルシューティング:

  • バックエンドサーバーの設定:
    • バックエンドサーバーが、プロキシサーバーのドメイン名やプロトコル(HTTP/HTTPS)を正しく認識するように設定されているか確認します。例えば、Tomcatなどのアプリケーションサーバーでは、RemoteIpValveproxyPort, proxyName などの設定が必要です。
    • SSL/TLSを扱う場合は、mod_sslSSLProxyEngine On が適切に設定されているか確認します。
  • ProxyPassReverse の確認:
    • ProxyPass と対になるように、必ず ProxyPassReverse を設定します。これは、バックエンドサーバーからのリダイレクト応答の Location ヘッダをApacheが書き換えるために必要です。
      ProxyPass /app/ http://backend-server.example.com/
      ProxyPassReverse /app/ http://backend-server.example.com/
      

SSL/TLS関連のエラー

エラーの症状:

  • 500 Internal Server Error などが返される。
  • ログに SSL handshake failederror:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure などのエラーが出力される。
  • HTTPSでのプロキシがうまくいかない。

原因:

  • SSL/TLSバージョンの不一致や、サポートされている暗号スイートの不一致。
  • バックエンドサーバーの証明書の問題(自己署名証明書、有効期限切れなど)。
  • SSLProxyEngine On が設定されていない。
  • mod_ssl がロードされていない。

トラブルシューティング:

  • SSL/TLSバージョンと暗号スイート:
    • バックエンドサーバーとApacheの間でサポートされているSSL/TLSバージョンや暗号スイートが一致しているか確認します。Apacheのログでエラーメッセージを詳しく見て、どの部分でハンドシェイクが失敗しているか特定します。SSLProxyProtocolSSLProxyCipherSuite などで調整が必要な場合があります。
  • 証明書の検証:
    • バックエンドサーバーの証明書が自己署名の場合や、検証エラーが発生する場合は、テスト環境でのみ SSLProxyCheckPeerCN OffSSLProxyVerify none などのディレクティブを使用して検証を一時的に無効にすることができます。ただし、本番環境ではセキュリティリスクが高いため、信頼できる証明書を使用するか、適切なCAの証明書を信頼リストに追加することを強く推奨します。

ProxyRequests On とオープンプロキシの危険性

エラーの症状:

  • サーバーが踏み台にされてしまう。
  • 意図せずフォワードプロキシとして機能し、外部からのアクセスが可能になってしまう。

原因:

  • ProxyRequests On を設定した場合に、<Proxy "*"> などで適切なアクセス制御を行っていない。
  • ProxyRequests On を安易に設定してしまっている。これはフォワードプロキシとして機能させるためのディレクティブであり、通常のリバースプロキシでは不要です。

トラブルシューティング:

  • もしフォワードプロキシとして使用する必要がある場合は、必ず <Proxy> ディレクティブ内で Require ipRequire host などを使用して、アクセス元を厳しく制限します。
    <Proxy "*">
        Require ip 192.168.1.0/24 # 内部ネットワークからのみ許可
    </Proxy>
    
  • リバースプロキシの場合、ProxyRequests On は設定しない。このディレクティブは、Apache を一般的なインターネットプロキシとして機能させるためのものであり、リバースプロキシの構築では不要です。

パフォーマンスに関する問題

エラーの症状:

  • Apache サーバーのリソース(CPU, メモリ)使用率が高い。
  • レスポンスが遅い、タイムアウトが頻繁に発生する。

原因:

  • Apache のワーカープロセス設定が不適切。
  • Apache とバックエンド間の接続が効率的でない(Keep-Aliveが有効でない、コネクションプールが不足しているなど)。
  • バックエンドサーバーの処理が遅い。

トラブルシューティング:

  • Apache の MPM (Multi-Processing Modules) 設定: サーバーの負荷に見合った MPM とその設定(例: MaxRequestWorkers, ThreadsPerChild など)を選択・調整します。
  • バックエンドサーバーの最適化: バックエンドアプリケーション自体のパフォーマンスを改善します。
  • ProxySet での調整:
    • ProxySet connectiontimeout=XX:バックエンドへの接続確立のタイムアウト
    • ProxySet keepalive=On:バックエンドとのKeep-Alive接続を有効にする(デフォルトで有効な場合が多い)
    • ProxySet max=<num>:プロキシのコネクションプールサイズを調整する。
  • ProxyTimeout の調整: 処理時間が長いリクエストのために適切に設定します。
  1. ログファイルの確認:
    • Apache の error_logaccess_log は常に最重要の情報源です。エラーが発生した時刻と関連するログメッセージを確認しましょう。
    • バックエンドサーバー側のログ(アプリケーションログ、ウェブサーバーログなど)も合わせて確認します。
  2. httpd -t コマンド:
    • 設定ファイルを変更した後は、必ず sudo apachectl configtest または sudo httpd -t を実行して構文エラーがないか確認します。
  3. 詳細なログ出力:
    • 一時的に LogLevel debug を設定すると、より詳細なデバッグ情報がログに出力され、問題の原因特定に役立つことがあります。
      LogLevel debug proxy:trace8
      
      proxy:trace8mod_proxy に関する非常に詳細なトレースログを出力します。問題解決後は元に戻すことを忘れないでください。
  4. 段階的な設定:
    • 複雑な設定をする場合は、まず最小限のシンプルなプロキシ設定から始め、それが機能することを確認してから、徐々に設定を追加していくと問題の切り分けがしやすくなります。


mod_proxy: <Proxy> の設定例

mod_proxy は、Apache HTTP Server をリバースプロキシとして機能させるための重要なモジュールです。<Proxy> ディレクティブは、プロキシの対象となるバックエンドサーバーに対して詳細な設定を適用するために使用されます。

以下の例では、一般的なユースケースにおける <Proxy> の使い方を示します。

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

これは最も基本的なリバースプロキシの設定です。クライアントから http://your-apache-server.com/app/ へのリクエストを、バックエンドサーバーの http://backend.example.com:8080/ へ転送します。

# 必要なモジュールのロード
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so # HTTP/HTTPSプロキシの場合

<VirtualHost *:80>
    ServerName your-apache-server.com

    # /app/ へのリクエストを http://backend.example.com:8080/ へプロキシ
    ProxyPass /app/ http://backend.example.com:8080/
    # バックエンドからのリダイレクトURLを書き換える
    ProxyPassReverse /app/ http://backend.example.com:8080/

    # <Proxy> ディレクティブでバックエンドサーバーに関する設定を行う
    <Proxy "http://backend.example.com:8080/">
        # プロキシ接続のタイムアウトを60秒に設定
        ProxyTimeout 60
        # バックエンドへの接続確立のタイムアウトを5秒に設定
        ProxySet connectiontimeout=5
        # オリジナルのHostヘッダをバックエンドに転送
        ProxyPreserveHost On
    </Proxy>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

解説:

  • ProxyPreserveHost On: クライアントからの Host ヘッダをそのままバックエンドサーバーに転送します。これにより、バックエンドサーバーが元のリクエストのドメイン名を認識できます。
  • ProxySet connectiontimeout=5: ApacheがバックエンドサーバーへのTCP接続を確立する際の最大時間を5秒に設定します。
  • ProxyTimeout 60: Apacheがバックエンドサーバーからの応答を待つ最大時間を60秒に設定します。
  • <Proxy "http://backend.example.com:8080/">: ここで、http://backend.example.com:8080/ というバックエンドサーバーにプロキシされるすべてのアクションに対する設定を定義します。
  • ProxyPassReverse /app/ http://backend.example.com:8080/: バックエンドサーバーが Location ヘッダ(リダイレクトなど)を含む応答を返した場合、そのURLをクライアントがアクセスした元のURL(/app/)に合わせて書き換えます。これにより、リダイレクトループなどを防ぎます。
  • ProxyPass /app/ http://backend.example.com:8080/: クライアントが http://your-apache-server.com/app/ にアクセスすると、Apache はそのリクエストを http://backend.example.com:8080/ に転送します。

HTTPS (SSL/TLS) を使用したプロキシ

バックエンドサーバーがHTTPSで動作している場合、mod_sslSSLProxyEngine On が必要になります。

# 必要なモジュールのロード
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule ssl_module modules/mod_ssl.so # SSL/TLSプロキシの場合

<VirtualHost *:443>
    ServerName your-apache-server.com
    SSLEngine On
    SSLCertificateFile /etc/ssl/certs/your-apache-server.crt
    SSLCertificateKeyFile /etc/ssl/private/your-apache-server.key

    # /secureapp/ へのリクエストを https://backend-secure.example.com:8443/ へプロキシ
    ProxyPass /secureapp/ https://backend-secure.example.com:8443/
    ProxyPassReverse /secureapp/ https://backend-secure.example.com:8443/

    # <Proxy> ディレクティブでHTTPSバックエンドに関する設定を行う
    <Proxy "https://backend-secure.example.com:8443/">
        SSLProxyEngine On # HTTPSプロキシを有効化
        # バックエンドの証明書検証を無効にする(非推奨、テスト環境のみ)
        # SSLProxyVerify none
        # SSLProxyCheckPeerCN Off
        # SSLProxyCheckPeerExpire Off

        # 必要に応じてその他の設定 (ProxyTimeout, ProxySet など)
        ProxyTimeout 120
    </Proxy>

    ErrorLog ${APACHE_LOG_DIR}/ssl_error.log
    CustomLog ${APACHE_LOG_DIR}/ssl_access.log combined
</VirtualHost>

解説:

  • SSLProxyVerify none / SSLProxyCheckPeerCN Off / SSLProxyCheckPeerExpire Off: これらの設定は、バックエンドサーバーのSSL証明書の検証を無効にします。セキュリティ上の理由から、本番環境では極力使用せず、正規の証明書を使用し、必要に応じてSSLProxyCACertificateFileなどで信頼するCA証明書を指定することを推奨します。
  • SSLProxyEngine On: これが最も重要で、Apacheがプロキシ先へのHTTPS接続を確立できるようにします。
  • LoadModule ssl_module modules/mod_ssl.so: SSL/TLS機能を使用するために mod_ssl をロードします。

ロードバランシング (mod_proxy_balancer を使用)

複数のバックエンドサーバー間でリクエストを分散させたい場合、mod_proxy_balancer を使用します。<Proxy> ディレクティブは、バランサー全体の設定や、個々のバランサーメンバー(バックエンドサーバー)の設定をカプセル化するために使われます。

# 必要なモジュールのロード
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 # ロードバランシング用
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so # ロードバランシングアルゴリズム

<VirtualHost *:80>
    ServerName your-apache-lb.com

    # "mycluster" という名前のバランサーを定義し、/app/ へのリクエストを転送
    ProxyPass /app/ balancer://mycluster/
    ProxyPassReverse /app/ balancer://mycluster/

    # <Proxy> ディレクティブでロードバランサーの設定を行う
    <Proxy balancer://mycluster>
        # バランサーのメンバーを定義
        BalancerMember http://backend1.example.com:8080 loadfactor=1 route=server1
        BalancerMember http://backend2.example.com:8080 loadfactor=1 route=server2

        # ロードバランシング方式(例: byrequests = リクエスト数に基づく)
        ProxySet lbmethod=byrequests

        # スティッキーセッションの設定(JSESSIONIDに基づいて同じサーバーに転送)
        ProxySet stickysession=JSESSIONID

        # サーバーの状態監視(5秒ごとにヘルスチェックを行い、失敗を3回許容)
        # BalancerMember に status= と failonstatus= で設定することも可能
        ProxySet hcmethod=GET hcuri=/healthz hcinterval=5s hcfailover=3

        # その他設定
        ProxyTimeout 300
    </Proxy>

    ErrorLog ${APACHE_LOG_DIR}/lb_error.log
    CustomLog ${APACHE_LOG_DIR}/lb_access.log combined
</VirtualHost>

解説:

  • ProxySet hcmethod=GET hcuri=/healthz hcinterval=5s hcfailover=3: バックエンドサーバーのヘルスチェック設定。
    • hcmethod: ヘルスチェックに使用するHTTPメソッド。
    • hcuri: ヘルスチェック用のURI。
    • hcinterval: ヘルスチェックの間隔(例: 5秒)。
    • hcfailover: 何回連続で失敗したらサーバーをダウンとみなすか。
  • ProxySet stickysession=JSESSIONID: クライアントの JSESSIONID クッキーに基づいて、同じセッションのリクエストを常に同じバックエンドサーバーに転送します。
  • ProxySet lbmethod=byrequests: ロードバランシングのアルゴリズムを設定します。
  • BalancerMember http://backend1.example.com:8080 loadfactor=1 route=server1: バランサーのメンバー(バックエンドサーバー)を定義します。
    • loadfactor: 負荷分散の重み付け。数値が大きいほど多くのリクエストを受け取ります。
    • route: スティッキーセッションで使用される、サーバーを一意に識別するID。
  • <Proxy balancer://mycluster>: balancer:// スキームを使用して、このバランサーグループ全体の設定を定義します。
  • ProxyPass /app/ balancer://mycluster/: /app/ へのリクエストを mycluster というバランサーグループに転送します。
  • LoadModule lbmethod_byrequests_module ...: リクエスト数によるロードバランシングを行うためのモジュールです。他にも lbmethod_bytraffic_module (トラフィック量) や lbmethod_heartbeat_module (バックエンドからのハートビート) などがあります。
  • LoadModule proxy_balancer_module ...: ロードバランシング機能を使うために必須です。

特定のIPアドレスからのプロキシアクセスを制限する

フォワードプロキシとして使用する場合(通常のリバースプロキシでは ProxyRequests Off のため不要ですが)、mod_proxy を利用したプロキシへのアクセスを制限する例です。

# 必要なモジュールのロード
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

# リバースプロキシとしてのみ使用する場合、これはコメントアウトするか Off に設定
# ProxyRequests On # フォワードプロキシ機能の有効化(注意して使用!)

<Proxy "*"> # すべてのプロキシリクエストに適用
    Order Deny,Allow
    Deny from all
    # 内部ネットワークからのアクセスのみを許可
    Allow from 192.168.1.0/24
    Allow from 10.0.0.0/8
</Proxy>

# リバースプロキシ設定の例
ProxyPass /internal-app/ http://internal-backend.example.com/
ProxyPassReverse /internal-app/ http://internal-backend.example.com/

解説:

  • ProxyRequests On: これはフォワードプロキシ機能を有効にするものであり、通常のリバースプロキシの目的では Off にしておくべきです。 On にすると、Apache がインターネット上の任意のサイトへのプロキシとして機能してしまう「オープンプロキシ」となり、悪用される危険性があります。
  • Order Deny,Allow / Deny from all / Allow from ...: 標準的なApacheのアクセス制御ディレクティブで、指定されたIPアドレス範囲からのアクセスのみを許可し、それ以外を拒否します。
  • <Proxy "*">: これは、mod_proxy を介したすべてのプロキシ接続に適用される設定です。
  • セキュリティ: 特にHTTPSプロキシやアクセス制御の設定では、セキュリティに十分注意し、安易な設定は避けるべきです。
  • ログの確認: 設定変更後は必ず Apache を再起動(またはリロード)し、error_log を確認してエラーがないか、意図した通りに動作しているかを確認しましょう。LogLeveldebug に一時的に変更すると、より詳細なプロキシの動作を確認できます。
  • ProxyPassProxyPassReverse: リバースプロキシでは、この2つのディレクティブをセットで使うのが基本です。
  • モジュールの有効化: 上記の例で示したように、使用する機能に応じて適切な LoadModule ディレクティブが httpd.conf またはそれにインクルードされるファイルに記述され、有効になっていることを確認してください。


mod_proxy<Proxy> ディレクティブは、特定のプロキシ先(バックエンドサーバー)に対して細かい設定を適用するのに役立ちます。しかし、すべてのシナリオで唯一の選択肢ではありません。

mod_rewrite の [P] フラグを使用する

mod_rewrite は Apache のURL書き換えモジュールで、非常に強力です。RewriteRule ディレクティブの [P] (Proxy) フラグを使用すると、マッチしたURLをプロキシ先に転送することができます。これは、ProxyPass<Proxy> よりも複雑な条件に基づくルーティングやURL書き換えが必要な場合に特に有効です。

特徴:

  • mod_proxy と同じプロキシエンジンを使用するため、基本的なプロキシ機能は共通。
  • クエリ文字列の操作も容易。
  • 正規表現による柔軟なマッチングと書き換えが可能。

設定例:

# 必要なモジュールのロード
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

<VirtualHost *:80>
    ServerName your-apache-server.com
    RewriteEngine On

    # /api/v1/user/123 のようなリクエストを /users/123 に書き換えてバックエンドにプロキシ
    RewriteRule "^/api/v1/user/(.*)$" "http://backend.example.com:8080/users/$1" [P,L]

    # /legacy-app/ へのリクエストを別のバックエンドにプロキシし、クエリ文字列を保持
    RewriteRule "^/legacy-app/(.*)$" "http://old-backend.example.com:80/legacy/$1" [P,L,QSA]

    # プロキシ先に対する特定のProxyTimeoutなどを設定したい場合は、
    # ProxyPassMatch と組み合わせるか、<Proxy>ディレクティブを併用します。
    # 例: ProxyPassMatch と組み合わせて特定のリライト先に適用
    # ProxyPassMatch "^/(.*)$" "http://backend.example.com:8080/$1" connectiontimeout=5 timeout=60

    # ただし、<Proxy> ディレクティブはプロキシされるURLの "スキーム://ホスト:ポート" 部分に適用されるため、
    # バックエンドのベースURLに対して設定することで、RewriteRule [P] で転送されたリクエストにも影響を与えられます。
    <Proxy "http://backend.example.com:8080/">
        ProxyTimeout 60
        ProxySet connectiontimeout=5
        ProxyPreserveHost On
    </Proxy>
    <Proxy "http://old-backend.example.com:80/">
        ProxyTimeout 120
    </Proxy>

    # ProxyPassReverse は RewriteRule [P] とは直接連携しないため、
    # 必要に応じて複数の ProxyPassReverse を記述するか、Header edit を検討します。
    ProxyPassReverse /api/v1/user/ http://backend.example.com:8080/users/
    ProxyPassReverse /legacy-app/ http://old-backend.example.com:80/legacy/

    ErrorLog ${APACHE_LOG_DIR}/rewrite_error.log
    CustomLog ${APACHE_LOG_DIR}/rewrite_access.log combined
</VirtualHost>
  • ProxyPassReverseRewriteRule [P] が書き換える前のクライアントのリクエストURLパスに対して設定するのが一般的です。バックエンドからのリダイレクトURLの書き換えは、複雑なケースでは mod_headersHeader edit ディレクティブも検討する必要があります。
  • [QSA] (Query String Append) フラグは、元のリクエストのクエリ文字列をプロキシ先のURLに付加します。
  • [L] (Last) フラグは、マッチした場合にそれ以降の RewriteRule の処理を停止させます。
  • [P] フラグは内部的に ProxyPass と同様の処理を行います。

ProxyPassMatch ディレクティブを使用する

ProxyPassMatchProxyPass の正規表現版です。クライアントからのリクエストURLパスを正規表現でマッチングし、プロキシ先に転送します。<Proxy> ディレクティブと異なり、ProxyPassMatch 自体にプロキシの挙動に関するパラメータ(例: timeout, connectiontimeout)を直接指定できるため、より簡潔に記述できる場合があります。

特徴:

  • <Proxy> ディレクティブと併用することで、より詳細な制御も可能。
  • ProxyPass 同様に、プロキシ固有のパラメータを直接指定できる。
  • URLパスの正規表現マッチングにより、ProxyPass よりも柔軟なルーティングが可能。

設定例:

# 必要なモジュールのロード
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

<VirtualHost *:80>
    ServerName your-apache-server.com

    # 数字IDを含む/products/ へのリクエストを http://backend.example.com:8080/item/ にプロキシ
    ProxyPassMatch "^/products/([0-9]+)$" "http://backend.example.com:8080/item/$1" timeout=60 connectiontimeout=5
    ProxyPassReverse /products/ http://backend.example.com:8080/item/

    # /api/ のすべてのリクエストを別のバックエンドにプロキシし、タイムアウトを長く設定
    ProxyPassMatch "^/api/(.*)$" "http://api.example.com:8080/v1/$1" timeout=300 connectiontimeout=10
    ProxyPassReverse /api/ http://api.example.com:8080/v1/

    # 上記のProxyPassMatchで設定されたバックエンドに対して、
    # さらに共通のProxyPreserveHostなどの設定を適用したい場合は<Proxy>も併用できます。
    <Proxy "http://backend.example.com:8080/">
        ProxyPreserveHost On
    </Proxy>
    <Proxy "http://api.example.com:8080/">
        ProxyPreserveHost On
    </Proxy>

    ErrorLog ${APACHE_LOG_DIR}/proxymatch_error.log
    CustomLog ${APACHE_LOG_DIR}/proxymatch_access.log combined
</VirtualHost>
  • 正規表現のキャプチャグループ ($1, $2 など) をプロキシ先のURLで使用できます。
  • ProxyPassMatchProxyPass と同様に、最も具体的なパスが最初に評価されます。

mod_proxy_express を使用する (大規模な動的プロキシの場合)

mod_proxy_express は、大量のバーチャルホストやバックエンドサービスを動的にプロキシする必要がある場合に検討されるモジュールです。特にマイクロサービスアーキテクチャなどで、Hostヘッダに基づいてプロキシ先をDBMファイルからルックアップするようなシナリオに適しています。これは、静的な ProxyPassRewriteRule の設定が膨大になりすぎるのを防ぐための代替手段です。

特徴:

  • 設定ファイルの変更なしにプロキシ先を追加・変更できる。
  • 大規模なバックエンドサーバー群に対応。
  • HostヘッダをキーとしてDBMファイルからプロキシ先を動的にルックアップ。

設定例:

  1. DBMファイルの作成: httxt2dbm ユーティリティを使用して、テキストファイルからDBMファイルを作成します。

    proxy_map.txt:

    app1.example.com http://backend-app1.example.com:8080/
    app2.example.com http://backend-app2.example.com:8081/
    

    コマンドでDBMファイルを作成:

    httxt2dbm -i proxy_map.txt -o /etc/apache2/conf/proxy_map
    
  2. Apache設定:

    # 必要なモジュールのロード
    LoadModule proxy_module modules/mod_proxy.so
    LoadModule proxy_http_module modules/mod_proxy_http.so
    LoadModule proxy_express_module modules/mod_proxy_express.so # これが重要
    
    <VirtualHost *:80>
        ServerName your-apache-lb.com # このサーバーに来るすべてのリクエストを対象
    
        # mod_proxy_express を有効化
        ProxyExpressEnable on
        # 作成したDBMファイルを指定
        ProxyExpressDBMFile /etc/apache2/conf/proxy_map
        # DBMファイルのタイプ(通常はデフォルトでOK)
        ProxyExpressDBMType default
    
        # <Proxy>ディレクティブは、DBMファイルによって動的に選択された
        # 各バックエンドURLに適用される共通の設定を提供できます。
        # 例: すべてのプロキシリクエストに適用されるタイムアウト
        <Proxy "*">
            ProxyTimeout 60
            ProxyPreserveHost On
        </Proxy>
    
        ErrorLog ${APACHE_LOG_DIR}/express_error.log
        CustomLog ${APACHE_LOG_DIR}/express_access.log combined
    </VirtualHost>
    
  • mod_proxy_balancer のような動的なロードバランシング機能とは異なる目的で、主に「動的なリバースプロキシスイッチ」として機能します。
  • mod_proxy_expressHost ヘッダに基づいてプロキシするため、通常はワイルドカードの ServerAlias を持つバーチャルホストや、単一のバーチャルホストで使用されます。

mod_jk (JServ Protocol - AJP) を使用する

Javaアプリケーションサーバー(Tomcat, JBossなど)の場合、HTTPプロキシではなく、AJP (Apache JServ Protocol) を使用する mod_jk モジュールが代替として利用されることがあります。AJPはHTTPよりも効率的で、ApacheとJavaアプリケーションサーバー間の連携を最適化するために設計されています。

特徴:

  • セッション管理やロードバランシング機能が充実。
  • HTTPプロキシよりも効率的なバイナリプロトコル(AJP)。
  • Javaアプリケーションサーバーに特化。

設定例:

  1. mod_jk モジュールのインストールとロード: (OSによってインストール方法が異なります。例: apt install libapache2-mod-jk

    LoadModule jk_module modules/mod_jk.so
    
  2. workers.properties ファイルの作成: このファイルで、Apacheが接続するJavaアプリケーションサーバーのワーカー(インスタンス)を定義します。

    /etc/apache2/conf/workers.properties

    worker.list=worker1,worker2,loadbalancer
    
    # worker1 の定義
    worker.worker1.port=8009
    worker.worker1.host=backend1.example.com
    worker.worker1.type=ajp13
    worker.worker1.lbfactor=1
    
    # worker2 の定義
    worker.worker2.port=8009
    worker.worker2.host=backend2.example.com
    worker.worker2.type=ajp13
    worker.worker2.lbfactor=1
    
    # ロードバランサーの定義
    worker.loadbalancer.type=lb
    worker.loadbalancer.balanced_workers=worker1,worker2
    worker.loadbalancer.sticky_session=True
    
  3. Apache設定:

    <VirtualHost *:80>
        ServerName your-apache-server.com
    
        # mod_jk の設定ファイルとログファイルを指定
        JkWorkersFile "/etc/apache2/conf/workers.properties"
        JkLogFile "${APACHE_LOG_DIR}/mod_jk.log"
        JkLogLevel info
        JkShmFile "${APACHE_LOG_DIR}/jk.shm"
    
        # /app/ へのリクエストを mod_jk のロードバランサーに転送
        JkMount /app/* loadbalancer
        JkMount /app loadbalancer # ルートパスも忘れずに
    
        # 必要に応じて、mod_jkのステータスページを有効化
        <Location /jkstatus>
            JkMount status
            Require ip 127.0.0.1 # アクセス制限
        </Location>
    
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>
    
  • JkMount ディレクティブは、どのURLパスをどのワーカーに転送するかを定義します。
  • mod_jk は、Java EEアプリケーションサーバーとの連携で高いパフォーマンスと安定性を求める場合に特に有用です。
  • mod_jkmod_proxy とは異なる独立したプロキシモジュールです。

mod_proxy: <Proxy> ディレクティブはApacheのリバースプロキシ設定の核となる部分ですが、以下のような代替手段や関連技術も存在します。

  • mod_jk: JavaアプリケーションサーバーとのAJP接続による最適化されたプロキシ。
  • mod_proxy_express: 大規模かつ動的にプロキシ先を決定したいマイクロサービス環境など。
  • ProxyPassMatch: 正規表現ベースのURLパスマッチングでプロキシ転送を行いたい場合。
  • mod_rewrite [P]: 複雑なURL書き換えとプロキシ転送を同時に行いたい場合。