Apacheのリバースプロキシでヘッダーを操作するときは、バックエンドへ送るリクエストを変更するRequestHeaderと、利用者へ返すレスポンスを変更するHeaderを使い分けます。レスポンスにAPIキーを追加すると利用者へ見えてしまい、認証やアクセス制御にもなりません。まず通信の向きと、変更したいヘッダーの目的を決めてください。

HeaderとRequestHeaderの違い
- RequestHeader:クライアントから受けたリクエストのヘッダーを調整します。リバースプロキシではバックエンドへ渡す値の設定に使えます。
- Header:クライアントへ送るレスポンスのヘッダーを調整します。アプリケーションが返す不要な情報の削除や、適切なセキュリティヘッダーの設定に使います。
- ProxyPassReverse:バックエンドのリダイレクト先など、特定のレスポンスヘッダーに含まれるURLを調整します。HTML本文やすべてのヘッダーを自動で変換する機能ではありません。
たとえば「X-AdminAccess: granted」を応答に付けても、管理画面の利用権限は制限できません。認証・認可はApacheの認可設定やアプリケーションで実装します。外から送られる任意のヘッダーを、そのまま利用者の本人確認として信頼しないでください。
設定例:応答情報の削除と安全な識別ヘッダー
以下は既存のHTTPS VirtualHostの一部へ加える例です。TLS設定そのものは省略しています。対象は/app/配下で、HTTPのバックエンドが同じホストの127.0.0.1:8080で待ち受ける構成です。転送先が別ホストなら、そのネットワークのアクセス制御とTLSの必要性も別に確認します。
# 既存のTLS VirtualHost内に追加する例
# mod_proxy / mod_proxy_http / mod_headers が必要
ProxyRequests Off
ProxyPass "/app/" "http://127.0.0.1:8080/"
ProxyPassReverse "/app/" "http://127.0.0.1:8080/"
<Location "/app/">
# バックエンドへ送る、秘密情報を含まない識別値
RequestHeader set X-Proxy-Route "app-gateway"
# クライアントへ返す応答ヘッダー
Header onsuccess unset X-Powered-By
Header always unset X-Powered-By
Header onsuccess unset X-Content-Type-Options
Header always set X-Content-Type-Options "nosniff"
</Location>
末尾のスラッシュを含め、ProxyPassの公開パスとバックエンドの対応を揃えます。ProxyRequests Offはフォワードプロキシを有効にしないための設定で、リバースプロキシの停止を意味しません。バックエンドを外部へ直接公開しない構成も確認します。
X-Proxy-Routeは経路を識別するだけの固定値で、認証情報ではありません。バックエンドで見えることを確認するために秘密のAPIキーをレスポンスへコピーする必要はありません。nosniffを追加する場合は、アプリが正しいContent-Typeを返すことも確かめてください。
onsuccessとalwaysの違いを意識する
Apacheには応答ヘッダーを保持する複数の内部テーブルがあります。単純に「Header set」を追加しただけでは、バックエンドやエラー応答の値と重複する場合があります。mod_headersの公式説明に沿って、不要な値をonsuccessとalwaysの両方から除き、設定する値の場所を揃えます。
alwaysを付けたから全状況で既存値をまとめて置換する、という意味ではありません。成功応答だけでなく、アプリのエラー、Apacheが生成するエラー、リダイレクトをそれぞれ調べることが必要です。CDNやロードバランサーが後段で変更する構成では、利用者が最終的に受け取る値も確認します。
Serverヘッダーは完全削除と情報縮小を区別する
Apache本体が生成するServerヘッダーは、Header unset Serverだけで必ず消せるものではありません。バージョン情報を減らすには、サーバー全体の設定で次を検討します。ServerTokens Prodでも「Server: Apache」という製品名は残ります。
ServerTokens Prod
ServerSignature Off
ServerSignatureはApacheが生成する一部のエラーページなどの署名表示を制御する設定です。ヘッダーの有無とは分けて確認します。製品名を隠すことは脆弱性修正の代わりにならないため、パッケージの更新と不要な機能の停止も続けます。
設定を保存する前後に確認する
設定ファイルをバックアップし、環境の管理コマンドでモジュール、VirtualHostの対応、構文を確認します。Debian系などではapache2ctl、別の環境ではapachectlやhttpdを使います。以下はapachectlの例です。
apachectl -M
apachectl -S
apachectl -t
構文が成功してから、その環境で決められた方法でreloadまたはgraceful reloadを行います。複数のVirtualHostがある場合、「後に書いたものが常に勝つ」と考えず、アドレスとHost名でどの設定が選ばれるかを-Sの結果で確認してください。
curl -sS -D - -o /dev/null https://example.com/app/
curlの例はGETのレスポンスヘッダーを確認します。example.comは自分の検証対象へ置き換えます。Windowsではcurl.exeと出力先NULを使えます。/app/の通常応答、404などのエラー、リダイレクトを調べ、X-Powered-Byがなく、意図したヘッダーが重複していないかを確認します。
リクエスト側の変更はクライアントの応答確認だけでは分からないため、バックエンドの検証用ログなどで受信値を確認します。Cookie、Authorization、APIキーなどの秘密をログへ出さないでください。
ヘッダー変更の完了条件は、要求と応答の両方向で意図した値を確認できることです。アプリの表示や認証、ダウンロードが壊れていないことまで確認し、問題があれば対象の変更を戻します。


コメント