🪶

エンハンスドLBで IP 制限が効かなかった理由:X‑Original‑For を使う必要があった話

に公開

何が起きたか

インターネット → CDN → さくらのエンハンスドLB → webサーバー
という構成でサーバーのApacheでcmsディレクトリに以下のようなIP制限を設定しようとしたところ、うまくいきませんでした

#mod_remoteip 設定
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy <LBのCIDR 範囲>

#cms ディレクトリへのアクセス制限
<Directory "/var/www/html/cms">
Require all denied
Require ip <許可するクライアントIP>
</Directory>

参考:mod_remoteip ドキュメント
https://httpd.apache.org/docs/current/mod/mod_remoteip.html

原因 : エンハンスドLBのHTTPヘッダー上書き

エンハンスドLBの前段にCDNなどがある場合、X-Forwarded-Forが上書きされてしまいます
代わりに元の値は X-Original-Forに保持されます
つまり、ApacheはX-Forwarded-Forではなく、X-Original-Forを参照する必要がありました

エンハンスドロードバランサへ接続した際のリクエストヘッダに X-Forwarded-For , X-Forwarded-Proto , X-Real-IP いずれかがすでにセットされている場合、実サーバへのプロキシ時のリクエストヘッダは以下のように書き換えられます。

(公式マニュアルより抜粋)

HTTPヘッダ 書き換え内容
X-Forwarded-For X-Forwarded-For → リクエスト元(前段プロキシなど)のIPアドレスに書き換え
X-Original-For → リクエスト時の X-Forwarded-For の値をセット
X-Forwarded-Proto X-Forwarded-Proto → リクエスト元(前段プロキシなど)接続時のプロトコル("http"もしくは"https")に書き換え
X-Original-Proto → リクエスト時の X-Forwarded-Proto の値をセット
X-Real-IP X-Real-IP → リクエスト元(前段プロキシなど)のIPアドレスに書き換え
X-Original-Real-IP → リクエスト時の X-Real-IP の値をセット

https://manual.sakura.ad.jp/cloud/appliance/enhanced-lb/index.html#http

ALBとの挙動の違い

一方で、AWS ALB(Application Load Balancer)では X-Forwarded-ForにクライアントIPを追記(append)するのがデフォルト仕様です
既存ヘッダーがあれば末尾に追加し、上書きは行いません

https://docs.aws.amazon.com/elasticloadbalancing/latest/application/x-forwarded-headers.html?utm_source=chatgpt.com#x-forwarded-for

対応 : Apache 側の設定変更

エンハンスドLBの前段にCDNなどFがあるような構成では、以下のように設定を変更することで、クライアントIPを正しく取得し、IP制限をかけることができました

#mod_remoteip 設定
RemoteIPHeader X-Original-For
RemoteIPTrustedProxy <エンハンスドLBのCIDR範囲>

#cms ディレクトリへのアクセス制限
<Directory "/var/www/html/cms">
Require all denied
Require ip <許可するクライアントIP>
</Directory>

まとめ

項目 AWS ALB(デフォルト) さくらのエンハンスドLB
X‑Forwarded‑Forの扱い 既存あれば追記、無ければ新規作成 前段ヘッダーあれば上書き
X‑Forwarded‑Forに値が合った場合の
元のクライアントIPの参照方法
X‑Forwarded‑Forの左端を参照 X-Original-For を参照

ベンダーによってLBの仕様が異なることをあまり意識していなかったので、今回の件はとても勉強になりました
また、ApacheやアプリケーションがX‑Forwarded‑Protoを参照するケースもあるため、さくらのエンハンスドLBを利用する場合は、上書き・保持のヘッダー仕様を事前に把握しておくことが重要だと感じました

Discussion