Apache mod_proxy: ProxyAddHeaders徹底解説 - リバースプロキシでのヘッダ転送

2025-05-27

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などのフレームワーク)がクライアントの情報を取得するために広く利用されます。例えば、ログの記録、アクセス制御、セッション管理などで使用されることがあります。

設定方法

ProxyAddHeadersOn または Off を指定します。

ProxyAddHeaders On

このディレクティブを On に設定すると、mod_proxy はリクエストをバックエンドサーバに転送する際に、上記の X-Forwarded-* ヘッダを自動的に追加します。デフォルトは Off です。

通常、ProxyPassProxyPassMatch ディレクティブと組み合わせて使用される 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 に設定することが推奨されます。
  • 設定場所の間違い: ProxyAddHeadersProxyPass ディレクティブや関連する VirtualHost または Location ブロックの外に設定されている、または適用範囲が間違っている。
  • mod_proxy が有効になっていない: mod_proxy と、mod_proxy_http などのプロトコル固有のモジュールがロードされていない場合。

トラブルシューティング

  • RequestHeader ディレクティブの併用: もし ProxyAddHeaders で追加されるヘッダに問題がある場合、mod_headersRequestHeader ディレクティブを使って、既存のヘッダをunsetしたり、強制的に追加したりすることで調整できます。
    • 例: RequestHeader unset X-Forwarded-For (ただし、これにより ProxyAddHeaders の機能が損なわれる可能性があるため、通常は推奨されません)
  • バックエンドアプリケーションの確認: バックエンドアプリケーション側で、X-Forwarded-For などのヘッダを正しく読み込んでいるか、または別のヘッダ名を期待していないか確認します。
  • Apacheのバージョン: httpd -v でApacheのバージョンを確認し、ProxyAddHeaders がサポートされているバージョンか確認します。
  • ProxyRequests の設定: リバースプロキシとして使用する場合は、必ず ProxyRequests Off を設定します。
  • 設定ファイルの確認: httpd -t で構文エラーがないか確認します。設定ファイル(httpd.confextra/httpd-vhosts.conf など)内で ProxyAddHeaders On が正しい VirtualHostLocation ブロック内に記述されているか確認します。
  • モジュールの確認: httpd -M | grep proxy を実行し、proxy_moduleproxy_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: ProxyAddHeadersOff に設定されているか、デフォルトの 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 など)を追加することがあります。アプリケーション側でこれらのヘッダも考慮に入れる必要があります。
  • ProxyAddHeaders On の確認: 設定ファイルで ProxyAddHeaders On が有効になっていることを確認します。

ホスト名やサーバ名が期待通りに転送されない

原因

  • X-Forwarded-Host の誤解釈: バックエンドアプリケーションが Host ヘッダではなく X-Forwarded-Host ヘッダを優先して読み込んでいる、またはその逆で混乱している。
  • ProxyPreserveHost Off: ProxyAddHeadersX-Forwarded-Host を追加しますが、元のクライアントの Host ヘッダをそのままバックエンドに転送するかどうかは ProxyPreserveHost ディレクティブが制御します。これが Off の場合、Apache自身の ServerNameHost ヘッダとしてバックエンドに転送されることがあります。

トラブルシューティング

  • 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_sslSSLProxyEngine On が必要です。ProxyAddHeaders 自体とは直接関係ありませんが、HTTPSプロキシ環境でヘッダが転送されない問題の一因となることがあります。
  • Apacheのエラーログ: /var/log/httpd/error_log (または設定されたパス) に、SSLハンドシェイクエラーや接続に関するエラーメッセージがないか確認します。
  • SSLProxyVerify/CheckPeer: デバッグ目的で、SSLProxyVerify noneSSLProxyCheckPeerCN 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_sslSSLProxyEngine 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>

解説

  • ProxyAddHeadersmod_remoteip の併用:
    • Apacheが単一のリバースプロキシとして機能する場合:
      • クライアントからのリクエストをApacheが受け取る際に mod_remoteip を使用して真のクライアントIPを特定します。
      • Apacheがそのリクエストをバックエンドにプロキシする際に ProxyAddHeaders を使用して X-Forwarded-For などのヘッダをバックエンドに転送します。
      • つまり、両者は異なる処理段階で連携して、クライアントIPの伝達を保証します。
    • Apacheの前に別のロードバランサー/プロキシがある場合は mod_remoteip が非常に有用です。
  • 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-HostX-Forwarded-Server のようなヘッダは自動的に追加されないため、これらが必要な場合は ProxyAddHeadersmod_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 の場合は自動)。
  • 設定がより複雑になりがち。