Apache mod_proxy: ProxyAddHeaders徹底解説 - リバースプロキシでのヘッダ転送
ProxyAddHeaders
は Apache HTTP Server の mod_proxy
モジュールが提供するディレクティブの一つです。このディレクティブは、リバースプロキシとして動作している Apache がバックエンドのサーバ(オリジンサーバ)にリクエストを転送する際に、特定のリクエストヘッダを自動的に追加するかどうかを制御します。
どのような目的で使用されるか
通常、リバースプロキシを介してアクセスされるWebアプリケーションでは、元のクライアントに関する情報(IPアドレス、ホスト名など)がバックエンドのサーバに直接伝わりません。これは、リクエストがApacheによって一旦受け取られ、その後Apacheからバックエンドサーバへ新しいリクエストとして送信されるためです。
このような状況で、バックエンドのアプリケーションがクライアントの真のIPアドレスなどを必要とする場合に、ProxyAddHeaders
が役立ちます。具体的には、以下の標準的なヘッダを自動的に追加します。
X-Forwarded-Server
: プロキシサーバのホスト名。X-Forwarded-Host
: クライアントがリクエストしたオリジナルのHost
ヘッダの値。X-Forwarded-For
: クライアントのオリジナルのIPアドレス。プロキシを介してリクエストが転送されるたびに、このヘッダにIPアドレスが追加されていきます。
これらのヘッダは、バックエンドのアプリケーション(例:PHP, Java, Node.jsなどのフレームワーク)がクライアントの情報を取得するために広く利用されます。例えば、ログの記録、アクセス制御、セッション管理などで使用されることがあります。
設定方法
ProxyAddHeaders
は On
または Off
を指定します。
ProxyAddHeaders On
このディレクティブを On
に設定すると、mod_proxy
はリクエストをバックエンドサーバに転送する際に、上記の X-Forwarded-*
ヘッダを自動的に追加します。デフォルトは Off
です。
通常、ProxyPass
や ProxyPassMatch
ディレクティブと組み合わせて使用される VirtualHost
または Location
ブロック内に配置されます。
例
<VirtualHost *:80>
ServerName example.com
ProxyRequests Off
ProxyPreserveHost On # クライアントのHostヘッダをバックエンドに転送
ProxyAddHeaders On # X-Forwarded-* ヘッダを追加
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://backend-server.local/
ProxyPassReverse / http://backend-server.local/
</VirtualHost>
上記の例では、example.com
へのアクセスが backend-server.local
にプロキシされ、その際に X-Forwarded-*
ヘッダが自動的に追加されます。
注意点
- 他のヘッダとの競合: もし、Apacheが転送する前に既に同じ名前の
X-Forwarded-*
ヘッダが存在していた場合、ProxyAddHeaders
は新しい情報を既存のヘッダに追加します(カンマ区切りで複数の値を持つ形になります)。 - セキュリティ:
X-Forwarded-For
ヘッダはクライアントから提供されるものではなく、プロキシサーバが追加するものです。しかし、クライアントが偽造したX-Forwarded-For
ヘッダを送信してきた場合、それが追加される可能性があります。バックエンドアプリケーションでこの情報を使用する際は、信頼できるプロキシからの情報であることを確認するなどの対策が必要になる場合があります。
ProxyAddHeaders
は、リバースプロキシ環境でクライアントの情報をバックエンドサーバに適切に伝えるための重要なディレクティブですが、設定ミスや予期しない挙動により問題が発生することがあります。
ヘッダがバックエンドに正しく転送されない
原因
- ヘッダの重複または上書き: バックエンドアプリケーションが期待するヘッダ名と、Apacheが自動的に追加するヘッダ名が競合している場合。
- Apacheのバージョンが古い:
ProxyAddHeaders
ディレクティブはApache 2.3.10以降で利用可能です。古いバージョンではこのディレクティブが認識されません。 ProxyRequests On
との競合: フォワードプロキシ設定(ProxyRequests On
)とリバースプロキシ設定(ProxyPass
)が混在している場合に予期しない挙動を示すことがあります。通常、リバースプロキシではProxyRequests Off
に設定することが推奨されます。- 設定場所の間違い:
ProxyAddHeaders
がProxyPass
ディレクティブや関連するVirtualHost
またはLocation
ブロックの外に設定されている、または適用範囲が間違っている。 mod_proxy
が有効になっていない:mod_proxy
と、mod_proxy_http
などのプロトコル固有のモジュールがロードされていない場合。
トラブルシューティング
- RequestHeader ディレクティブの併用: もし
ProxyAddHeaders
で追加されるヘッダに問題がある場合、mod_headers
のRequestHeader
ディレクティブを使って、既存のヘッダをunsetしたり、強制的に追加したりすることで調整できます。- 例:
RequestHeader unset X-Forwarded-For
(ただし、これによりProxyAddHeaders
の機能が損なわれる可能性があるため、通常は推奨されません)
- 例:
- バックエンドアプリケーションの確認: バックエンドアプリケーション側で、
X-Forwarded-For
などのヘッダを正しく読み込んでいるか、または別のヘッダ名を期待していないか確認します。 - Apacheのバージョン:
httpd -v
でApacheのバージョンを確認し、ProxyAddHeaders
がサポートされているバージョンか確認します。 ProxyRequests
の設定: リバースプロキシとして使用する場合は、必ずProxyRequests Off
を設定します。- 設定ファイルの確認:
httpd -t
で構文エラーがないか確認します。設定ファイル(httpd.conf
やextra/httpd-vhosts.conf
など)内でProxyAddHeaders On
が正しいVirtualHost
やLocation
ブロック内に記述されているか確認します。 - モジュールの確認:
httpd -M | grep proxy
を実行し、proxy_module
とproxy_http_module
(HTTPプロキシの場合) がロードされていることを確認します。ロードされていなければ、LoadModule proxy_module modules/mod_proxy.so
などを設定ファイルに追加し、Apacheを再起動します。
クライアントのIPアドレスが取得できない/間違っている
原因
- バックエンドアプリケーションの読み込みミス: アプリケーション側が
X-Forwarded-For
を読み込まず、直接接続元のIPアドレス(ApacheのIPアドレス)を拾っている。 - 途中のプロキシ: Apacheの前にもロードバランサー(例: ELB, Nginx)やCDNなど別のプロキシが存在し、それらが
X-Forwarded-For
ヘッダを適切に引き継いでいない、または独自のヘッダを追加している。 ProxyAddHeaders Off
:ProxyAddHeaders
がOff
に設定されているか、デフォルトのOff
のままになっている。
トラブルシューティング
- Apacheのアクセスログの調整: Apacheのアクセスログ(
CustomLog
)で、%h
だけでなく、%{X-Forwarded-For}i
などのヘッダ情報も記録するように設定すると、デバッグに役立ちます。- 例:
LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined_proxy
- 例:
- アプリケーションログの確認: バックエンドアプリケーションのアクセスログやデバッグログで、実際に受け取っているヘッダの内容を確認します。
- 多段プロキシの確認:
- もしApacheの前に別のプロキシがある場合、そのプロキシが
X-Forwarded-For
ヘッダを正しく設定しているか確認します。多くの場合、複数のX-Forwarded-For
ヘッダがある場合はカンマ区切りで追加されていきます(例:X-Forwarded-For: client_ip, proxy1_ip, proxy2_ip
)。バックエンドアプリケーションは通常、リストの最初のIPアドレスを真のクライアントIPとして扱います。 - 一部のロードバランサー(特にクラウドサービス)は
X-Forwarded-For
以外に独自のヘッダ(例:True-Client-IP
など)を追加することがあります。アプリケーション側でこれらのヘッダも考慮に入れる必要があります。
- もしApacheの前に別のプロキシがある場合、そのプロキシが
ProxyAddHeaders On
の確認: 設定ファイルでProxyAddHeaders On
が有効になっていることを確認します。
ホスト名やサーバ名が期待通りに転送されない
原因
X-Forwarded-Host
の誤解釈: バックエンドアプリケーションがHost
ヘッダではなくX-Forwarded-Host
ヘッダを優先して読み込んでいる、またはその逆で混乱している。ProxyPreserveHost Off
:ProxyAddHeaders
はX-Forwarded-Host
を追加しますが、元のクライアントのHost
ヘッダをそのままバックエンドに転送するかどうかはProxyPreserveHost
ディレクティブが制御します。これがOff
の場合、Apache自身のServerName
がHost
ヘッダとしてバックエンドに転送されることがあります。
トラブルシューティング
X-Forwarded-Server
の利用:X-Forwarded-Server
はApacheのServerName
を示し、プロキシサーバの識別に使用されます。これもバックエンドアプリケーションが参照することで、プロキシ経由であることが判断できます。- アプリケーションのヘッダ処理: バックエンドアプリケーションが
Host
ヘッダとX-Forwarded-Host
ヘッダのどちらを優先して利用しているか確認します。多くの場合、リバースプロキシ環境ではX-Forwarded-Host
を参照するようにアプリケーションを調整します。 ProxyPreserveHost On
の確認: クライアントがリクエストしたオリジナルのHost
ヘッダをバックエンドに転送したい場合は、ProxyPreserveHost On
を設定します。
SSL/TLS関連の問題 (特にHTTPSプロキシの場合)
原因
- 証明書検証の問題: バックエンドサーバのSSL証明書が自己署名であったり、有効期限が切れていたり、信頼できないCAによって署名されていたりする場合、Apacheが接続に失敗し、結果としてヘッダが転送されないことがあります。
SSLProxyEngine On
の不足: ApacheがHTTPSリクエストをバックエンドのHTTPSサーバにプロキシする場合、mod_ssl
のSSLProxyEngine On
が必要です。ProxyAddHeaders
自体とは直接関係ありませんが、HTTPSプロキシ環境でヘッダが転送されない問題の一因となることがあります。
- Apacheのエラーログ:
/var/log/httpd/error_log
(または設定されたパス) に、SSLハンドシェイクエラーや接続に関するエラーメッセージがないか確認します。 - SSLProxyVerify/CheckPeer: デバッグ目的で、
SSLProxyVerify none
やSSLProxyCheckPeerCN off
を一時的に設定して接続できるか確認します(本番環境ではセキュリティリスクがあるため注意が必要です)。バックエンドサーバの証明書が適切に設定されていることを確認するのが根本的な解決策です。 SSLProxyEngine On
の設定: HTTPSプロキシを使用する場合は、SSLProxyEngine On
を忘れずに設定します。
一般的なトラブルシューティングのヒント
- 設定変更後の再起動/リロード: Apacheの設定を変更した後は、必ず
apachectl configtest
で構文チェックを行い、apachectl graceful
またはapachectl restart
で設定を反映させます。 - バックエンドアプリケーションのデバッグ: バックエンドアプリケーションで、受け取ったHTTPリクエストヘッダをすべてログに出力するなどのデバッグ機能を利用し、Apacheからどのようなヘッダが送られているかを正確に把握します。
- ネットワーク接続の確認: Apacheからバックエンドサーバへのネットワーク到達性(ファイアウォール、ルーティング、ポートなど)を確認します。
curl
コマンドをApacheサーバからバックエンドサーバに向けて実行し、直接アクセスできるかテストします。 - Apacheのエラーログとアクセスログを徹底的に確認する: 最も重要な情報源です。
LogLevel debug
に設定すると、より詳細なプロキシの挙動に関するログが出力され、問題の特定に役立ちます。ただし、本番環境で長時間debug
に設定するとディスク容量を圧迫する可能性があるため注意が必要です。
mod_proxy: ProxyAddHeaders
は、Apache HTTP Server の設定ファイル(通常 httpd.conf
や、conf.d/
ディレクトリ内のVhost設定ファイルなど)に記述するディレクティブであり、プログラミングというよりは設定に近いです。
ここでは、一般的なユースケースにおける ProxyAddHeaders
の設定例と、それに関連する他の重要なディレクティブを組み合わせて説明します。
事前準備:必要なモジュールの有効化
ProxyAddHeaders
を含む mod_proxy
の機能を使用するには、以下のモジュールがApacheにロードされている必要があります。
httpd.conf
またはそれにインクルードされている設定ファイルに、以下の LoadModule
ディレクティブが存在し、コメントアウトされていないことを確認してください。
# プロキシ機能のコアモジュール
LoadModule proxy_module modules/mod_proxy.so
# HTTPプロキシのためのモジュール (最も一般的)
LoadModule proxy_http_module modules/mod_proxy_http.so
# (もしHTTPSバックエンドにプロキシする場合)
# LoadModule proxy_balancer_module modules/mod_proxy_balancer.so # ロードバランシングを使う場合
# LoadModule proxy_ftp_module modules/mod_proxy_ftp.so # FTPプロキシを使う場合
# LoadModule proxy_ajp_module modules/mod_proxy_ajp.so # AJPプロキシを使う場合 (Tomcatなど)
# LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so # FastCGIプロキシを使う場合
# LoadModule proxy_scgi_module modules/mod_proxy_scgi.so # SCGIプロキシを使う場合
# LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so # WebSocketプロキシを使う場合
設定例 1: 基本的なリバースプロキシ設定で X-Forwarded-*
ヘッダを追加する
この最も一般的なシナリオでは、ApacheがバックエンドのWebアプリケーションサーバ(例: Node.js, Python, PHP-FPM, Tomcatなど)へのリクエストをプロキシします。
# 仮想ホストの設定例
<VirtualHost *:80>
ServerName example.com
#ServerAlias www.example.com
# リバースプロキシとして動作させるため、フォワードプロキシ機能を無効化
ProxyRequests Off
# クライアントがリクエストしたオリジナルのHostヘッダをバックエンドに転送
# これにより、バックエンドはexample.comとしてリクエストを受け取ります。
ProxyPreserveHost On
# **重要**: X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Server ヘッダを自動的に追加
ProxyAddHeaders On
# プロキシ対象のパスとバックエンドサーバのアドレスを設定
# / への全てのアクセスを http://192.168.1.100:8080/ へプロキシ
ProxyPass / http://192.168.1.100:8080/
# バックエンドからのリダイレクトURLを書き換え、クライアント側から見て正しいURLになるようにする
ProxyPassReverse / http://192.168.1.100:8080/
# プロキシディレクティブの範囲内でアクセス制御を定義
# この例では、全てのアクセスを許可
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>
解説
ProxyPassReverse / http://192.168.1.100:8080/
: バックエンドサーバがリダイレクト応答(例:Location
ヘッダ)を返す場合に、そのURLをクライアント側から見て正しいもの(example.com
)に書き換えます。ProxyPass / http://192.168.1.100:8080/
:/
へのリクエストをhttp://192.168.1.100:8080/
へ転送します。ProxyAddHeaders On
: これが今回の主役です。この設定により、Apacheはバックエンドサーバへリクエストを転送する際に、以下のヘッダを自動的に追加します。X-Forwarded-For
: クライアントのIPアドレス(複数プロキシを経由した場合、カンマ区切りで連なる)X-Forwarded-Host
: クライアントがリクエストしたオリジナルのHost
ヘッダの値X-Forwarded-Server
: プロキシしているApacheサーバのホスト名
ProxyPreserveHost On
: クライアントがApacheに送信したHost
ヘッダ(この場合example.com
)を、そのままバックエンドサーバに転送します。これにより、バックエンドアプリケーションは、オリジナルのドメイン名でアクセスされたかのように処理できます。ProxyRequests Off
: Apacheをリバースプロキシとしてのみ機能させ、外部からのフォワードプロキシとしての利用を防ぎます。
設定例 2: 特定のパスのみをプロキシし、ヘッダを追加する
Webサイトの一部(例: /api/
パス)のみを特定のバックエンドAPIサーバにプロキシし、それ以外はローカルのApacheで処理する場合。
<VirtualHost *:80>
ServerName api.example.com
ProxyRequests Off
ProxyPreserveHost On
ProxyAddHeaders On # APIバックエンドにヘッダを転送
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
# /api/ への全てのアクセスを http://192.168.1.200:3000/ へプロキシ
ProxyPass /api/ http://192.168.1.200:3000/
ProxyPassReverse /api/ http://192.168.1.200:3000/
# (もし必要であれば、他のパスはローカルのDocumentRootから提供)
# DocumentRoot "/var/www/html/api_frontend"
# <Directory "/var/www/html/api_frontend">
# AllowOverride None
# Require all granted
# </Directory>
ErrorLog ${APACHE_LOG_DIR}/api.example.com-error.log
CustomLog ${APACHE_LOG_DIR}/api.example.com-access.log combined
</VirtualHost>
解説
ProxyPass
のパス指定が/api/
となっているため、このパスにマッチするリクエストのみがプロキシされます。- この設定では、
api.example.com/api/
へのリクエストがhttp://192.168.1.200:3000/
へ転送され、その際にX-Forwarded-*
ヘッダが追加されます。
設定例 3: アクセスログで X-Forwarded-For
ヘッダを利用する
ProxyAddHeaders
が追加した情報を、Apacheのアクセスログ(CustomLog
)で記録するように設定できます。これにより、バックエンドサーバにアクセスせずとも、Apacheのログからクライアントの真のIPアドレスなどを確認できます。
# httpd.conf またはログ設定ファイル
# LogFormat ディレクティブの定義
# '%h' の代わりに '%{X-Forwarded-For}i' を使用することで、元のクライアントIPを記録
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" proxy_combined
# CustomLog ディレクティブで使用
<VirtualHost *:80>
ServerName example.com
ProxyRequests Off
ProxyPreserveHost On
ProxyAddHeaders On
ProxyPass / http://192.168.1.100:8080/
ProxyPassReverse / http://192.168.1.100:8080/
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
# ここで proxy_combined フォーマットを使用
CustomLog ${APACHE_LOG_DIR}/example.com-access.log proxy_combined
</VirtualHost>
解説
- これにより、ログの最初のフィールドが、Apacheに直接接続してきたIPアドレス(
%h
)ではなく、X-Forwarded-For
ヘッダに含まれるクライアントのオリジナルIPアドレスになります。 %{X-Forwarded-For}i
は、受信したリクエストヘッダX-Forwarded-For
の値をログに記録する指示です。LogFormat
ディレクティブでproxy_combined
という新しいログフォーマットを定義しています。
設定例 4: HTTPSバックエンドへのプロキシ
バックエンドサーバがHTTPSで動作している場合、mod_ssl
の SSLProxyEngine On
が必要になります。
# 必要なモジュールの有効化
# LoadModule ssl_module modules/mod_ssl.so
# 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 # (もしバックエンドがAJPの場合)
<VirtualHost *:443>
ServerName secure.example.com
SSLEngine On
SSLCertificateFile /etc/ssl/certs/secure.example.com.crt
SSLCertificateKeyFile /etc/ssl/private/secure.example.com.key
# SSLCertificateChainFile /etc/ssl/certs/ca-bundle.crt # 必要に応じて
ProxyRequests Off
ProxyPreserveHost On
ProxyAddHeaders On # X-Forwarded-* ヘッダを追加
# HTTPSバックエンドへのプロキシを有効化
SSLProxyEngine On
# (オプション) バックエンドSSL証明書の検証設定
# SSLProxyVerify require # バックエンド証明書を厳密に検証する場合
# SSLProxyVerifyDepth 10
# SSLProxyCACertificateFile /path/to/backend_ca_certs.pem # バックエンド証明書を検証するためのCA証明書
ProxyPass / https://192.168.1.100:8443/
ProxyPassReverse / https://192.168.1.100:8443/
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ErrorLog ${APACHE_LOG_DIR}/secure.example.com-error.log
CustomLog ${APACHE_LOG_DIR}/secure.example.com-access.log combined
</VirtualHost>
ProxyAddHeaders On
はこれまでと同様に機能し、バックエンドにX-Forwarded-*
ヘッダが送信されます。SSLProxyEngine On
: これが重要です。ApacheがバックエンドのHTTPSサーバとSSL/TLS接続を確立できるようにします。SSLEngine On
およびSSLCertificateFile
/SSLCertificateKeyFile
は、Apache自体がクライアントからのHTTPSリクエストを受け入れるための設定です。
mod_headers モジュールによる手動でのヘッダ追加
mod_headers
モジュールを使用すると、HTTPリクエストおよびレスポンスヘッダをより細かく制御できます。ProxyAddHeaders
が自動的に追加するヘッダを、このモジュールを使って手動で追加することも可能です。これにより、特定のヘッダのみを追加したり、値の形式を調整したりといった柔軟性が得られます。
必要なモジュール
mod_headers.so
設定例
# mod_headers を有効化
LoadModule headers_module modules/mod_headers.so
<VirtualHost *:80>
ServerName example.com
ProxyRequests Off
ProxyPreserveHost On
# ProxyAddHeaders Off (または未設定) の場合
# X-Forwarded-For ヘッダを RequestHeader で追加
# "%{REMOTE_ADDR}s" はクライアントのオリジナルIPアドレス (mod_remoteipが有効でない場合)
# 既に X-Forwarded-For が存在する場合は、カンマ区切りで追加されます。
RequestHeader append X-Forwarded-For "%{REMOTE_ADDR}s"
# X-Forwarded-Host ヘッダを RequestHeader で追加
# "%{Host}i" はクライアントが送ってきたオリジナルのHostヘッダの値
RequestHeader append X-Forwarded-Host "%{Host}i"
# X-Forwarded-Server ヘッダを RequestHeader で追加
# "%{SERVER_NAME}s" はApacheサーバのServerNameディレクティブの値
RequestHeader append X-Forwarded-Server "%{SERVER_NAME}s"
ProxyPass / http://192.168.1.100:8080/
ProxyPassReverse / http://192.168.1.100:8080/
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>
解説
%
で始まる変数は、Apacheが提供する様々なリクエスト情報やサーバ情報を参照するためのフォーマット文字列です。%{REMOTE_ADDR}s
: Apacheに接続してきたリモートクライアントのIPアドレス(通常は直前のプロキシまたはクライアントのIP)。%{Host}i
: 受信したリクエストのHost
ヘッダの値。%{SERVER_NAME}s
: 現在のApacheサーバのServerName
ディレクティブで設定されたホスト名。
RequestHeader append HeaderName Value
: 指定したHeaderName
のヘッダにValue
を追加します。もし同じ名前のヘッダが既に存在する場合、HTTP標準に従ってカンマ区切りで値が追加されます。
利点
- 特定の条件に基づいてヘッダを追加・変更・削除できる。
ProxyAddHeaders
が提供しない、より細かいヘッダの制御が可能。
欠点
- ヘッダの追加ロジックを自分で管理する必要がある。
ProxyAddHeaders
に比べて設定が冗長になる可能性がある。
mod_remoteip モジュールによるログの修正と REMOTE_ADDR の上書き
mod_remoteip
は、ロードバランサーやリバースプロキシ(Apache自身ではないもの)の背後にあるApacheサーバで、クライアントの真のIPアドレスをApacheのログ(%h
や %a
フォーマット)やCGI環境変数 REMOTE_ADDR
に反映させるためのモジュールです。これは ProxyAddHeaders
がバックエンドに X-Forwarded-For
を送るのとは異なる目的ですが、最終的にアプリケーションが真のIPアドレスを得るという点では共通します。
必要なモジュール
mod_remoteip.so
設定例
# mod_remoteip を有効化
LoadModule remoteip_module modules/mod_remoteip.so
# クライアントIPアドレスを X-Forwarded-For ヘッダから取得する
RemoteIPHeader X-Forwarded-For
# 信頼するプロキシのIPアドレスまたはネットワーク範囲を指定
# ここに記載されたIPアドレスからの X-Forwarded-For ヘッダのみが信頼されます。
# 複数指定可能。
RemoteIPTrustedProxy 192.168.1.1 # 例: Apacheの前にいるロードバランサーのIP
RemoteIPTrustedProxy 10.0.0.0/8 # 例: 内部ネットワークからのプロキシ
# あるいは、内部プロキシ(プライベートIPアドレス)を信頼する場合
# RemoteIPInternalProxy 192.168.1.0/24
<VirtualHost *:80>
ServerName example.com
# ... 他のVirtualHost設定 ...
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
# CustomLog で %a を使用すると、mod_remoteipによって修正されたIPアドレスが記録される
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
# mod_remoteip を使用する場合、通常は ProxyAddHeaders は不要だが、
# バックエンドにも X-Forwarded-Host などが必要な場合は併用する。
# ProxyAddHeaders On
ProxyPass / http://192.168.1.100:8080/
ProxyPassReverse / http://192.168.1.100:8080/
</VirtualHost>
解説
ProxyAddHeaders
とmod_remoteip
の併用:- Apacheが単一のリバースプロキシとして機能する場合:
- クライアントからのリクエストをApacheが受け取る際に
mod_remoteip
を使用して真のクライアントIPを特定します。 - Apacheがそのリクエストをバックエンドにプロキシする際に
ProxyAddHeaders
を使用してX-Forwarded-For
などのヘッダをバックエンドに転送します。 - つまり、両者は異なる処理段階で連携して、クライアントIPの伝達を保証します。
- クライアントからのリクエストをApacheが受け取る際に
- Apacheの前に別のロードバランサー/プロキシがある場合は
mod_remoteip
が非常に有用です。
- Apacheが単一のリバースプロキシとして機能する場合:
mod_remoteip
は、Apache自身がリバースプロキシとしてバックエンドにリクエストを送る際のヘッダ追加(ProxyAddHeaders
の役割)ではなく、Apache自身がリクエストを受け取る際に、上流プロキシからの情報を元にクライアントIPを修正するモジュールです。mod_remoteip
が有効な場合、Apacheの内部的なクライアントIPアドレス(REMOTE_ADDR
)がX-Forwarded-For
ヘッダの真のクライアントIPに上書きされます。これにより、Apacheのアクセスログ(%a
や%h
フォーマットを使用した場合)や、Apache上で動作するCGI/PHPスクリプトなどから取得する$_SERVER['REMOTE_ADDR']
が正しいクライアントIPを返すようになります。RemoteIPInternalProxy
:RemoteIPTrustedProxy
と同様ですが、内部ネットワークからのプライベートIPアドレスも信頼する場合に使用します。RemoteIPTrustedProxy
: 指定されたIPアドレスまたはCIDRブロックからの接続の場合に限り、X-Forwarded-For
ヘッダを信頼します。これにより、悪意のあるクライアントがX-Forwarded-For
を偽装して送ってきた場合に、Apacheがそれを信じることを防ぎます。RemoteIPHeader X-Forwarded-For
:X-Forwarded-For
ヘッダからクライアントIPを取得するようにApacheに指示します。
利点
- 信頼するプロキシのIPを厳密に定義することで、セキュリティを向上できる。
- Apacheのログ (
%h
や%a
) やCGI環境変数 (REMOTE_ADDR
) が直接真のクライアントIPを反映するようになるため、アプリケーションの修正が不要になる場合がある。
欠点
X-Forwarded-Host
やX-Forwarded-Server
のようなヘッダは自動的に追加されないため、これらが必要な場合はProxyAddHeaders
やmod_headers
との併用が必要。
mod_rewrite と [P] フラグ (mod_proxy との組み合わせ)
mod_rewrite
は非常に強力なURL書き換えモジュールですが、ProxyPass
の代替としてプロキシを行うことも可能です。RewriteRule
ディレクティブの [P]
(Proxy) フラグを使用すると、マッチしたリクエストをプロキシできます。この方法でも ProxyAddHeaders
は有効です。
必要なモジュール
mod_rewrite.so
, mod_proxy.so
, mod_proxy_http.so
設定例
# mod_rewrite を有効化
LoadModule rewrite_module modules/mod_rewrite.so
<VirtualHost *:80>
ServerName example.com
ProxyRequests Off
ProxyPreserveHost On
ProxyAddHeaders On # [P] フラグによるプロキシでも有効
RewriteEngine On
# /api/ にマッチするリクエストをプロキシ
RewriteRule "^/api/(.*)$" "http://192.168.1.200:3000/$1" [P,L]
# プロキシディレクティブの範囲内でアクセス制御を定義
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
# RewriteRule の [P] フラグでは ProxyPassReverse は自動的に機能しないため、
# 必要に応じて明示的に記述する (通常は必須)
ProxyPassReverse /api/ http://192.168.1.200:3000/
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>
解説
mod_rewrite
を使用する場合も、ProxyAddHeaders On
は通常通り機能し、X-Forwarded-*
ヘッダがバックエンドに転送されます。RewriteRule "^/api/(.*)$" "http://192.168.1.200:3000/$1" [P,L]
:/api/
で始まるURLをhttp://192.168.1.200:3000/
にプロキシします。[P]
フラグがプロキシ処理を指示し、[L]
フラグはこのルールが適用されたら他のルールを処理しないことを意味します。
利点
mod_rewrite
の正規表現による強力なURLマッチング機能と組み合わせてプロキシを設定できる。複雑なルーティングルールが必要な場合に有効。
ProxyPassReverse
を手動で記述する必要がある(ProxyPass
の場合は自動)。- 設定がより複雑になりがち。