BIG-IP の X-Forwarded-For 設定|SNAT 環境でクライアント IP を通知

  • URLをコピーしました!
目次

はじめに

F5 BIG-IP などのロードバランサーを導入した後、Web サーバーのアクセスログを確認すると、クライアントの IP アドレスではなく、すべて BIG-IP の IP アドレスが記録されているケースがあります。

本記事では、この事象を解決する標準的な手法である 「X-Forwarded-For(XFF)」 の設定方法について解説します。なぜクライアント IP が届かないのか(SNAT の仕組み)から、BIG-IP での具体的な設定手順、設定が反映されない場合の確認方法までを整理します。

本記事の設定手順・コマンドは TMOS 17.5 系を基準に記載しています。XFF 挿入の設定項目および iRule コマンドは v13 以降で共通して利用できますが、GUI のメニュー表示はバージョンにより一部異なる場合があります。

この記事でわかること
  • なぜ Web サーバーにクライアント IP が届かないのか(SNAT の仕組み)
  • X-Forwarded-For の役割とフォーマット
  • BIG-IP で XFF を挿入する具体的な設定手順(HTTP プロファイル)
  • 設定が反映されない場合の確認方法

なぜ IP が変わってしまうのか(SNAT の仕組み)

BIG-IP は通常、フルプロキシ(Full Proxy) として動作します。この際、行きと帰りの通信経路を確実に BIG-IP 経由とするために、SNAT(Source NAT) が使われるのが一般的です。

SNAT なし

サーバーからの戻り通信が BIG-IP を経由せず、直接クライアントへ返ってしまい、DSR 構成以外では通信が成立しません。

SNAT あり

BIG-IP が送信元 IP を自身(BIG-IP)に書き換えてサーバーへ送信します。これにより戻り通信も確実に BIG-IP へ返ります。

通信成立に必要な SNAT ですが、副作用として 「Web サーバーに届くパケットの送信元 IP が、すべて BIG-IP のものになる」 という事象が発生します。この課題を解決するのが XFF です。

X-Forwarded-For(XFF)とは

X-Forwarded-For(XFF)は、HTTP ヘッダフィールドの一つです。ロードバランサーやプロキシサーバーを経由した際に、本来のクライアント IP アドレスを Web サーバーへ伝えるための手段として広く使用されています。

なお、XFF は事実上の標準として普及していますが、正式な標準仕様としては RFC 7239 で定義された Forwarded ヘッダが存在します。現状の多くの環境では XFF が用いられているため、本記事では XFF を中心に解説します。

通信フローとヘッダの変化

パケットの内容がどのように変化するかの概略は以下のとおりです。

Client → BIG-IP

送信元 IP は Client です。この時点では XFF ヘッダはありません。

BIG-IP(処理中)

SNAT で送信元 IP を BIG-IP に書き換えると同時に、HTTP ヘッダへ X-Forwarded-For: <Client IP> を挿入します。

BIG-IP → Server

Web サーバーには送信元 BIG-IP として届きますが、XFF ヘッダを参照することで本来のクライアント IP を把握できます。

XFF のフォーマット

XFF フィールドは以下の形式で記述されます。

X-Forwarded-For: <クライアントIP>, <プロキシ1>, <プロキシ2>...

例: X-Forwarded-For: 203.0.113.10

複数のプロキシを経由する場合、カンマ区切りで IP アドレスが追記されます。通常、一番左端の IP アドレスが大元のクライアント IP になります。

参考: Services Profiles(F5 公式 / BIG-IP 16.0)
“When you configure the BIG-IP system to insert this header, the target server can identify the request as coming from a client other than the client that initiated the connection. The default setting is Disabled.”
(このヘッダを挿入するよう設定すると、ターゲットサーバーは接続を開始したクライアントとは別のクライアントからのリクエストであることを識別できます。デフォルト設定は無効です。)
https://techdocs.f5.com/en-us/bigip-16-0-0/big-ip-local-traffic-management-profiles-reference/services-profiles.html

BIG-IP での設定手順(HTTP プロファイル)

BIG-IP で XFF を挿入するには、Virtual Server に適用されている HTTP プロファイル を編集します。運用上のトラブルを避けるため、デフォルトの http プロファイルを直接書き換えるのではなく、新しいカスタムプロファイルを作成して適用する手順をおすすめします。

STEP
HTTP プロファイルの作成
  1. 管理画面のメニューから「Local Traffic」>「Profiles」>「Services」>「HTTP」をクリックします(バージョンにより「Local Traffic」>「Profiles」>「HTTP」と表示される場合があります)
  1. 画面右上の「Create」ボタンをクリックします。
  1. Name に任意のプロファイル名を入力します(例: http_xff_profile
  2. Parent Profile が http になっていることを確認します。
STEP
「Insert X-Forwarded-For」の有効化
  1. 設定画面の中ほどにある「Settings」エリアを表示します。
  2. Insert X-Forwarded-For の項目で、チェックボックス(Custom)にチェックを入れます。
  3. プルダウンメニューから「Enabled」を選択します。
  4. 画面最下部の「Finished」をクリックして保存します。
STEP
Virtual Server への適用
  1. 「Local Traffic」>「Virtual Servers」を開き、対象の Virtual Server をクリックします。
  2. Configuration セクションの HTTP Profile(Client)プルダウンから、作成したプロファイル(例: http_xff_profile)を選択します。
  3. 「Update」をクリックして適用は完了です。

動作確認

設定後、XFF ヘッダが実際に挿入されているかを確認します。

方法①: tcpdump でパケットの内容を確認する

BIG-IP の CLI(SSH)で tcpdump を実行し、サーバーへ送られるパケットの内容を直接確認する方法が確実です。Web サーバー側のインターフェース(VLAN)を指定してキャプチャします。-A オプションでヘッダの内容(ASCII 文字)を表示できます。

# internal VLAN 向けの通信、かつポート 80 番をキャプチャ
tcpdump -ni internal -A port 80

通信を発生させると、リクエスト行(GET / HTTP/1.1 など)の下に XFF ヘッダが表示されます。

GET / HTTP/1.1
Host: example.com
User-Agent: curl/7.68.0
Accept: */*
X-Forwarded-For: 192.168.100.10  <-- これが表示されれば成功

後から Wireshark で詳細に確認したい場合は、-w /var/tmp/xff.pcap を付与してファイルに保存する方法もおすすめです。詳細は関連記事『Wireshark のフィルタ書き方と複数条件の使い分け|TCP 再送と HTTP エラーの追跡』もあわせて参照してください。

方法②: Web サーバーのアクセスログで確認する

Web サーバー(Apache、Nginx、IIS)のアクセスログでも確認できます。ただし、Web サーバー側で XFF の値をログに記録する設定が入っていないと、ログには表示されません。 BIG-IP の設定が正しくても、この点でつまずきやすいため注意が必要です。

  • Apache の場合: LogFormat%{X-Forwarded-For}i を追加します。
  • Nginx の場合: ログフォーマットに $http_x_forwarded_for 変数を追加します。
  • IIS の場合: 「Advanced Logging」モジュールなどを利用し、フィールドを追加します。

さらに、アクセス制御や統計処理でクライアント IP を「正しい送信元 IP」として扱いたい場合は、ログ記録だけでなく、Apache では mod_remoteip、Nginx では ngx_http_realip_module の設定もおすすめします。これらを設定すると、XFF の値をリモートアドレスとして反映できます。

「BIG-IP の設定をしたのにログが変わらない」という場合は、Web サーバー側のログフォーマット設定が原因である可能性が高く、まずは方法①(tcpdump)での確認をおすすめします。

設定前に押さえておきたい制約・注意点

XFF の挿入は手順自体はシンプルですが、構成によっては機能しない、あるいは意図しない値が記録される場合があります。設定前に以下を確認することをおすすめします。

L7(HTTP プロファイル)が前提

Insert X-Forwarded-For は HTTP ヘッダを操作する機能のため、HTTP プロファイルが適用された Standard タイプの Virtual Server でのみ機能します。Performance (HTTP) や Fast L4 ベースの構成では HTTP ヘッダを書き換えられず、XFF は挿入されません。「設定したのに挿入されない」場合は、まず Virtual Server のタイプと HTTP プロファイルの適用状況を確認することをおすすめします。

HTTPS 通信では SSL ターミネーションが必要

通信が HTTPS で暗号化されている場合、BIG-IP がヘッダを読み書きするには、Client SSL プロファイルで一度復号(SSL ターミネーション)している必要があります。クライアントからサーバーまで暗号化したまま通す SSL パススルー構成では、BIG-IP は HTTP ヘッダを操作できないため、XFF の挿入はできません。

標準動作は「追記(Append)」であり、偽装対策は別途必要

プロファイルの Insert X-Forwarded-For は、リクエストに既存の XFF ヘッダがある場合、それを削除せずに追記します。このため、悪意あるクライアントが偽の X-Forwarded-For を付与して送信すると、偽の IP がそのままログに残る可能性があります。信頼できないネットワークからの通信を扱う場合は、後述の iRule による上書き、または以下の信頼設定の利用を検討することをおすすめします。

X-Forwarded-For header acceptance(Trust XFF)

リクエストに含まれる XFF ヘッダのクライアント IP と統計情報を信頼するかどうかを制御する設定です。

Alternate X-Forwarded-For headers

デフォルトの X-Forwarded-For 以外のヘッダ名を指定する設定です。複数指定する場合は半角スペースで区切ります。

参考: Services Profiles(F5 公式 / BIG-IP 16.0)
“This setting enables or disables trusting the client IP address, and statistics from the client IP address, based on the request’s X-Forwarded-For (XFF) headers, if they exist.”
(この設定は、リクエストに XFF ヘッダが存在する場合に、その XFF ヘッダに基づくクライアント IP アドレスおよびその統計情報を信頼するかどうかを有効化または無効化します。)
https://techdocs.f5.com/en-us/bigip-16-0-0/big-ip-local-traffic-management-profiles-reference/services-profiles.html

HTTP プロファイル方式と iRule 方式の使い分け

XFF の挿入には、HTTP プロファイルを使う方法と iRule を使う方法があります。基本的には処理負荷が低く設定も容易な HTTP プロファイル方式が第一候補ですが、条件分岐や偽装ヘッダの除去が必要な場合は iRule 方式が適しています。

比較軸HTTP プロファイル方式iRule 方式
設定の手軽さ容易(チェックボックスのみ)スクリプト記述が必要
処理負荷低いプロファイル方式よりやや高い
条件分岐(パス・送信元など)不可可能
既存ヘッダの除去・上書き不可(追記のみ)可能
推奨ケース全通信に一律で挿入したい特定条件のみ/偽装対策が必要

iRule の設定例

iRule を使う場合の最もシンプルな例は以下のとおりです。

when HTTP_REQUEST {
    # クライアントの IP アドレスを X-Forwarded-For ヘッダとして挿入
    HTTP::header insert X-Forwarded-For [IP::client_addr]
}

既存ヘッダを削除して上書きする場合(偽装対策)は以下のようになります。

when HTTP_REQUEST {
    # 偽装防止のため、既存の XFF ヘッダがあれば削除
    if { [HTTP::header exists X-Forwarded-For] } {
        HTTP::header remove X-Forwarded-For
    }
    # 改めて正しい IP を挿入
    HTTP::header insert X-Forwarded-For [IP::client_addr]
}

なお、[IP::client_addr] はクライアントの IP アドレスを返すコマンドで、HTTP_REQUEST(クライアント側コンテキスト)では clientside { IP::remote_addr } と等価です。他記事で [IP::remote_addr] を用いた例を見かけることがありますが、このコンテキストでは同じ結果になります。

参考: IP::client_addr(F5 公式 iRules リファレンス)
“Returns the client IP address of a connection. This command is equivalent to the command clientside { IP::remote_addr }”
(接続のクライアント IP アドレスを返します。このコマンドは clientside { IP::remote_addr } と等価です。)
https://clouddocs.f5.com/api/irules/IP__client_addr.html

補足: クライアント IP を通知する他の方式

XFF は HTTP 通信向けの方式ですが、用途や通信種別によっては他の方式が適する場合があります。設計時の参考として概要を整理します。

方式対象レイヤ概要
X-Forwarded-For(XFF)L7(HTTP)事実上の標準。HTTP ヘッダにクライアント IP を付与
Forwarded(RFC 7239)L7(HTTP)正式な標準仕様。送信元・プロトコル等を 1 つのヘッダで表現
PROXY ProtocolL4TCP 接続の先頭に送信元情報を付与。HTTP 以外の通信でも利用可能

HTTP 以外の通信や、暗号化したまま通す構成でクライアント IP を伝えたい場合は、PROXY Protocol が選択肢になります。

まとめ

本記事では、BIG-IP 環境でクライアント IP を Web サーバーへ伝える X-Forwarded-For(XFF)の設定について解説しました。

  • SNAT 環境では送信元 IP が BIG-IP に書き換わるため、XFF でクライアント IP を補完する。
  • XFF の挿入は HTTP プロファイルの Insert X-Forwarded-For を有効化するのが基本。
  • L7(HTTP プロファイル)適用が前提で、HTTPS では SSL ターミネーションが必要。
  • 標準動作は追記のため、偽装対策が必要な場合は iRule や信頼設定を検討する。
  • 設定後は tcpdump または Web サーバーのアクセスログで挿入を確認する。
  • 実 IP として扱うには Web サーバー側で mod_remoteip / realip module 等の設定もあわせて行う。

ロードバランサー導入後にログの送信元 IP が揃ってしまう事態を避けるため、構築段階での設定をおすすめします。

以上、最後までお読みいただきありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

関西を拠点に活動する、現役インフラエンジニア。経験20年超。

大手通信キャリアにて、中〜大規模インフラ(ネットワーク・サーバ・クラウド・セキュリティ)の設計・構築およびプロジェクトマネジメントに従事。現場で直面した技術課題への対処や、最新の脆弱性情報への実務対応を、一次情報として発信しています。

保有資格
CCIE Lifetime Emeritus(取得から20年以上)/ VCAP-DCA / Azure Solutions Architect Expert

▶ 運営者プロフィール(詳細)

目次