real_ip_header / set_real_ip_from の正しい設計(X-Forwarded-Forを安全に扱う方法)

  • URLをコピーしました!

ロードバランサ(LB)やプロキシ配下でnginxを使う場合、

real_ip_header / set_real_ip_from の設計を誤ると、IP制限が簡単に突破されます。

にもかかわらず、

  • とりあえずX-Forwarded-Forを使う
  • サンプル設定をそのまま流用する

といった導入が非常に多いのが実情です。

本記事では、

  • この2つのディレクティブが何をしているのか
  • なぜ設計を誤ると危険なのか
  • 安全な設定例と判断基準
  • 正しく動いていることの確認方法

を、実務レベルで解説します。

目次

まず結論:信頼境界を明確にしない設定は危険

real_ip_header / set_real_ip_from は、

「どのIPから来たX-Forwarded-Forを信頼するか」

を定義する仕組みです。

ここが曖昧だと、

誰でも送信元IPを偽装できる状態になります。

それぞれの役割

① real_ip_header

どのHTTPヘッダを「本当のクライアントIP」として扱うかを指定します。

real_ip_header X-Forwarded-For;

つまり、

「XFFの値でremote_addrを書き換える」

という意味です。

② set_real_ip_from

そのヘッダを

「信頼してよい送信元IP」

を指定します。

set_real_ip_from 10.0.0.0/24;

ここに書かれていないIPから来たXFFは無視されます。

最も危険な誤設定

❌ 例1:set_real_ip_from を書いていない

この状態でreal_ip_headerを有効にすると、

全てのXFFを信頼する状態になります。

つまり、

curl -H "X-Forwarded-For: 127.0.0.1" http://example.com

でIP偽装が可能になります。

❌ 例2:0.0.0.0/0 を指定

set_real_ip_from 0.0.0.0/0;

これは「全世界を信頼する」という意味です。

実質的にセキュリティ無効化です。

安全な設計の基本原則

  • 信頼できるLB / ProxyのIPだけを書く
  • 直接アクセス経路を遮断する
  • 上書き動作を理解する

安全な設定例(LB配下構成)

set_real_ip_from 10.0.0.10;   # LBのIP
real_ip_header X-Forwarded-For;
real_ip_recursive on;

ポイント解説

  • LBのIPのみ信頼
  • direct accessはFWで遮断
  • real_ip_recursive on で多段プロキシ対応

real_ip_recursive の意味

XFFが複数IPを持つ場合、

X-Forwarded-For: client, proxy1, proxy2

recursiveがoffだと、

最後のIPだけを見る

可能性があります。

onにすると、

信頼できるIPを辿り、最初の非信頼IPを採用

します。

正しく設定できているかの確認方法

① remote_addr の確認

log_format test '$remote_addr - $http_x_forwarded_for';

ログで、

  • remote_addr が期待IPになっているか
  • XFFと整合性が取れているか

を確認します。

② 直接アクセス時の挙動

LBを経由せずアクセスし、

XFFが無視されることを確認

します。

設計判断まとめ

  • real_ip_header は「IP書き換えスイッチ」
  • set_real_ip_from は「信頼境界」
  • 境界を曖昧にするとIP偽装可能

この2つは便利ですが、

“どの経路を信頼するか”を明確に定義できる場合のみ使うべき

です。

まとめ(覚えておくべき一文)

set_real_ip_from は「信頼する装置だけ」を書く。広く書かない。

この原則を守れば、

X-Forwarded-Forは安全に扱えます。

目次