Apache HTTP Serverでリバースプロキシを構築:mod_proxyとの設定例
mod_proxy: <Proxy>
とは?
mod_proxy
は Apache HTTP Server のモジュールで、HTTP リクエストを別のサーバー(バックエンドサーバー)に転送する、つまり「プロキシ」として機能するための機能を提供します。このプロキシ機能の設定において、<Proxy>
ディレクティブはプロキシの対象となる URL パスを定義し、そのパスに対するプロキシの挙動を制御するために使用されます。
簡単に言えば、Apache が特定のリクエストを受け取った際に、そのリクエストをどこに転送するか、どのように転送するかを設定するための「箱」のようなものです。
<Proxy>
ディレクティブの構文
基本的な構文は以下のようになります。
<Proxy url-path>
... 設定ディレクティブ ...
</Proxy>
url-path
: プロキシの対象となる URL のパスを指定します。これは、クライアントからのリクエスト URL のパス部分とマッチングされます。具体的には、プロトコル、ホスト、ポートを含まないパス部分です。
<Proxy>
ディレクティブの主な用途と機能
<Proxy>
ディレクティブ内では、以下のような様々な設定を行うことができます。
-
プロキシ対象の定義: 最も基本的な機能です。例えば、
/app/
というパスへのリクエストを別のサーバーに転送したい場合、以下のように記述します。<Proxy "http://backend-server.example.com/"> # このバックエンドサーバーへのプロキシに関する設定 </Proxy>
この例では、
http://backend-server.example.com/
がプロキシの対象となるバックエンドサーバーのベース URL です。 -
プロキシのアクセス制御: 特定のクライアント IP アドレスからのプロキシアクセスを許可または拒否できます。これは
<Directory>
や<Location>
と同様に、Require
ディレクティブなどを用いて行います。<Proxy "http://backend-server.example.com/api/"> Require ip 192.168.1.0/24 </Proxy>
この場合、
192.168.1.x
のネットワークからのアクセスのみが/api/
へのプロキシを許可されます。 -
環境変数の設定: プロキシされたリクエストに特定の環境変数を設定することができます。これはバックエンドサーバーが、プロキシ経由のリクエストであることを認識したり、追加情報を受け取ったりするのに役立ちます。
<Proxy "http://backend-server.example.com/"> SetEnv PROXY_VIA_APACHE 1 </Proxy>
-
ロードバランシング (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.conf
やconf-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
ProxyPass
にdisablereuse=on
を追加します。ProxyPass /app/ http://backend-server.example.com/ disablereuse=on
- まれに、Keep-Alive接続が原因で問題が発生することがあります。以下のディレクティブを試してみてください。
- タイムアウト設定の調整:
ProxyTimeout
ディレクティブの値を増やしてみます。デフォルトは非常に短い場合があります。ProxyTimeout 300 # 300秒 (5分) に設定
- ファイアウォールの確認:
- Apache サーバーからバックエンドサーバーへの接続が、サーバーのOSレベルのファイアウォール(iptables/firewalldなど)やネットワーク機器のファイアウォールによってブロックされていないか確認します。
- 設定の確認:
ProxyPass
ディレクティブや<Proxy>
ディレクティブで指定されているバックエンドサーバーのIPアドレス、ホスト名、ポート番号が正しいか再確認します。- スペルミスがないか、特にスラッシュ
/
の有無が重要です。ProxyPass /app/ http://backend-server.example.com/
のように、両方に末尾のスラッシュを付けるか、両方につけないか、一貫性を持たせるのが一般的です。
- バックエンドサーバーの稼働確認:
- バックエンドサーバーが実際に起動しているか確認します。
- Apache サーバーから
curl
やtelnet
コマンドでバックエンドサーバーにアクセスできるか確認します。# 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などのアプリケーションサーバーでは、
RemoteIpValve
やproxyPort
,proxyName
などの設定が必要です。 - SSL/TLSを扱う場合は、
mod_ssl
とSSLProxyEngine On
が適切に設定されているか確認します。
- バックエンドサーバーが、プロキシサーバーのドメイン名やプロトコル(HTTP/HTTPS)を正しく認識するように設定されているか確認します。例えば、Tomcatなどのアプリケーションサーバーでは、
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 failed
やerror:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
などのエラーが出力される。 - HTTPSでのプロキシがうまくいかない。
原因:
- SSL/TLSバージョンの不一致や、サポートされている暗号スイートの不一致。
- バックエンドサーバーの証明書の問題(自己署名証明書、有効期限切れなど)。
SSLProxyEngine On
が設定されていない。mod_ssl
がロードされていない。
トラブルシューティング:
- SSL/TLSバージョンと暗号スイート:
- バックエンドサーバーとApacheの間でサポートされているSSL/TLSバージョンや暗号スイートが一致しているか確認します。Apacheのログでエラーメッセージを詳しく見て、どの部分でハンドシェイクが失敗しているか特定します。
SSLProxyProtocol
やSSLProxyCipherSuite
などで調整が必要な場合があります。
- バックエンドサーバーとApacheの間でサポートされているSSL/TLSバージョンや暗号スイートが一致しているか確認します。Apacheのログでエラーメッセージを詳しく見て、どの部分でハンドシェイクが失敗しているか特定します。
- 証明書の検証:
- バックエンドサーバーの証明書が自己署名の場合や、検証エラーが発生する場合は、テスト環境でのみ
SSLProxyCheckPeerCN Off
やSSLProxyVerify none
などのディレクティブを使用して検証を一時的に無効にすることができます。ただし、本番環境ではセキュリティリスクが高いため、信頼できる証明書を使用するか、適切なCAの証明書を信頼リストに追加することを強く推奨します。
- バックエンドサーバーの証明書が自己署名の場合や、検証エラーが発生する場合は、テスト環境でのみ
ProxyRequests On とオープンプロキシの危険性
エラーの症状:
- サーバーが踏み台にされてしまう。
- 意図せずフォワードプロキシとして機能し、外部からのアクセスが可能になってしまう。
原因:
ProxyRequests On
を設定した場合に、<Proxy "*">
などで適切なアクセス制御を行っていない。ProxyRequests On
を安易に設定してしまっている。これはフォワードプロキシとして機能させるためのディレクティブであり、通常のリバースプロキシでは不要です。
トラブルシューティング:
- もしフォワードプロキシとして使用する必要がある場合は、必ず
<Proxy>
ディレクティブ内でRequire ip
やRequire 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
の調整: 処理時間が長いリクエストのために適切に設定します。
- ログファイルの確認:
- Apache の
error_log
とaccess_log
は常に最重要の情報源です。エラーが発生した時刻と関連するログメッセージを確認しましょう。 - バックエンドサーバー側のログ(アプリケーションログ、ウェブサーバーログなど)も合わせて確認します。
- Apache の
httpd -t
コマンド:- 設定ファイルを変更した後は、必ず
sudo apachectl configtest
またはsudo httpd -t
を実行して構文エラーがないか確認します。
- 設定ファイルを変更した後は、必ず
- 詳細なログ出力:
- 一時的に
LogLevel debug
を設定すると、より詳細なデバッグ情報がログに出力され、問題の原因特定に役立つことがあります。LogLevel debug proxy:trace8
proxy:trace8
はmod_proxy
に関する非常に詳細なトレースログを出力します。問題解決後は元に戻すことを忘れないでください。
- 一時的に
- 段階的な設定:
- 複雑な設定をする場合は、まず最小限のシンプルなプロキシ設定から始め、それが機能することを確認してから、徐々に設定を追加していくと問題の切り分けがしやすくなります。
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_ssl
と SSLProxyEngine 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
を確認してエラーがないか、意図した通りに動作しているかを確認しましょう。LogLevel
をdebug
に一時的に変更すると、より詳細なプロキシの動作を確認できます。 ProxyPass
とProxyPassReverse
: リバースプロキシでは、この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>
ProxyPassReverse
はRewriteRule [P]
が書き換える前のクライアントのリクエストURLパスに対して設定するのが一般的です。バックエンドからのリダイレクトURLの書き換えは、複雑なケースではmod_headers
のHeader edit
ディレクティブも検討する必要があります。[QSA]
(Query String Append) フラグは、元のリクエストのクエリ文字列をプロキシ先のURLに付加します。[L]
(Last) フラグは、マッチした場合にそれ以降のRewriteRule
の処理を停止させます。[P]
フラグは内部的にProxyPass
と同様の処理を行います。
ProxyPassMatch ディレクティブを使用する
ProxyPassMatch
は ProxyPass
の正規表現版です。クライアントからのリクエスト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で使用できます。 ProxyPassMatch
はProxyPass
と同様に、最も具体的なパスが最初に評価されます。
mod_proxy_express を使用する (大規模な動的プロキシの場合)
mod_proxy_express
は、大量のバーチャルホストやバックエンドサービスを動的にプロキシする必要がある場合に検討されるモジュールです。特にマイクロサービスアーキテクチャなどで、Hostヘッダに基づいてプロキシ先をDBMファイルからルックアップするようなシナリオに適しています。これは、静的な ProxyPass
や RewriteRule
の設定が膨大になりすぎるのを防ぐための代替手段です。
特徴:
- 設定ファイルの変更なしにプロキシ先を追加・変更できる。
- 大規模なバックエンドサーバー群に対応。
- HostヘッダをキーとしてDBMファイルからプロキシ先を動的にルックアップ。
設定例:
-
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
-
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_express
はHost
ヘッダに基づいてプロキシするため、通常はワイルドカードのServerAlias
を持つバーチャルホストや、単一のバーチャルホストで使用されます。
mod_jk (JServ Protocol - AJP) を使用する
Javaアプリケーションサーバー(Tomcat, JBossなど)の場合、HTTPプロキシではなく、AJP (Apache JServ Protocol) を使用する mod_jk
モジュールが代替として利用されることがあります。AJPはHTTPよりも効率的で、ApacheとJavaアプリケーションサーバー間の連携を最適化するために設計されています。
特徴:
- セッション管理やロードバランシング機能が充実。
- HTTPプロキシよりも効率的なバイナリプロトコル(AJP)。
- Javaアプリケーションサーバーに特化。
設定例:
-
mod_jk
モジュールのインストールとロード: (OSによってインストール方法が異なります。例:apt install libapache2-mod-jk
)LoadModule jk_module modules/mod_jk.so
-
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
-
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_jk
はmod_proxy
とは異なる独立したプロキシモジュールです。
mod_proxy: <Proxy>
ディレクティブはApacheのリバースプロキシ設定の核となる部分ですが、以下のような代替手段や関連技術も存在します。
mod_jk
: JavaアプリケーションサーバーとのAJP接続による最適化されたプロキシ。mod_proxy_express
: 大規模かつ動的にプロキシ先を決定したいマイクロサービス環境など。ProxyPassMatch
: 正規表現ベースのURLパスマッチングでプロキシ転送を行いたい場合。mod_rewrite [P]
: 複雑なURL書き換えとプロキシ転送を同時に行いたい場合。