Nginxで実際の訪問者IPではなくプロキシIPが表示される問題を修正する

intermediate Nginx2026-07-14| Linux (Ubuntu, CentOS, Debian)上のNginx、Cloudflare、AWS ELB/ALB、HAProxy、またはNginx Ingress Controller。

Error Message

Nginx access logs display internal IPs (like 127.0.0.1 or 10.0.0.x) instead of the actual visitor's public IP address.
#nginx#devops#cloudflare#networking

要約:クイック修正

ログがプロキシのIPで埋め尽くされている場合は、ngx_http_realip_moduleが必要です。通常はhttpまたはserverブロック内に以下の行を追加して、どのソースを信頼するかをNginxに伝えます。

# CloudflareのIP範囲を信頼する
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
# ... 必要に応じて他の範囲を追加 ...

# 実際のIPが含まれているヘッダーを定義
real_ip_header CF-Connecting-IP; 
real_ip_recursive on;

sudo nginx -s reloadを実行して変更を適用します。

なぜこの現象が起きるのか?

NginxをCloudflareやAWS Load Balancerのようなサービスの背後に配置すると、直接のTCP接続はプロキシのIPから行われます。デフォルトでは、Nginxはこの直近の接続元をクライアントとして記録します。その結果、実際にサイトを閲覧している人物ではなく、172.x.x.x10.x.x.xのアドレスがログに表示されることになります。

通常、プロキシは元のIPを特別なHTTPヘッダーに含めて渡します。一般的なものにはX-Forwarded-ForCF-Connecting-IPがあります。あなたの役割は、プロキシのIPを無視し、代わりにそのヘッダーの値を使用するようNginxに設定することです。

ステップバイステップの設定方法

1. モジュールのサポートを確認する

ほとんどのモダンなNginxビルドには、最初からreal_ipモジュールが含まれています。以下のコマンドを実行して確認できます。

nginx -V 2>&1 | grep --color 'with-http_realip_module'

出力に--with-http_realip_moduleがハイライトされていれば、準備完了です。そうでない場合は、nginx-extrasパッケージをインストールするか、ソースから再コンパイルする必要があります。

2. 信頼できるプロキシをホワイトリストに登録する

ここではセキュリティが重要です。実際に管理または使用しているソースからのIPヘッダーのみを信頼するようにしてください。ホワイトリスト化することで、悪意のあるユーザーが偽のヘッダーを送信して身元を隠す「IPスプーフィング(なりすまし)」を防ぐことができます。

シナリオA:Cloudflareを利用している場合

Cloudflareは特定のIP範囲を使用しています。管理しやすくするために、/etc/nginx/conf.d/cloudflare.confに専用の設定ファイルを作成します。

# Cloudflare IPv4範囲(例として一部を抜粋)
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;

# Cloudflare IPv6範囲
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;

# Cloudflareは常にこのヘッダーで実際のIPを送信します
real_ip_header CF-Connecting-IP;

シナリオB:AWS ALBやHAProxyの背後にいる場合

内部ロードバランサーを使用している場合は、VPC CIDR(例:172.31.0.0/16)またはバランサーの特定のプライベートIPを使用します。

set_real_ip_from 172.31.0.0/16;  # AWS VPC範囲の例
set_real_ip_from 10.0.0.0/8;      # 内部ネットワーク
real_ip_header X-Forwarded-For;
real_ip_recursive on;

**プロのヒント:**CloudflareがAWS ALBにリクエストを送り、それがさらにNginxに送られるような多層構造の場合は、常にreal_ip_recursive on;を使用してください。これにより、Nginxはヘッダー内のIPリスト全体を確認し、信頼できるリストに含まれていない最後のIP(=本来のクライアントIP)を選択するようになります。

3. ログフォーマットの調整

real_ipが有効になると、標準の$remote_addr変数は自動的に更新されます。カスタムログフォーマットを使用している場合は、それが$remote_addrを参照していることを確認してください。nginx.confでの一般的な設定は以下のようになります。

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent"';

修正の確認方法

アクセスログを確認する

ターミナルを開き、リアルタイムでログを監視します。

tail -f /var/log/nginx/access.log

スマートフォンやVPNからウェブサイトにアクセスしてください。ローカルの10.x.x.xアドレスではなく、実際のパブリックIP(例:1.2.3.4)が表示されるはずです。

スクリプトによる方法

ウェブディレクトリに簡単なinfo.phpファイルを配置して、Nginxがアプリケーションに何を渡しているかを確認します。

<?php
 echo "Real IP: " . $_SERVER['REMOTE_ADDR'];
?>

避けるべき一般的な間違い

- **全世界を信頼する:**決して`set_real_ip_from 0.0.0.0/0;`を使用しないでください。これを行うと、誰でもリクエストに`X-Forwarded-For`ヘッダーを追加するだけでIPアドレスを偽装できてしまいます。
- **IPv6を忘れる:**訪問者がIPv6を使用していても、IPv4の範囲しかホワイトリストに登録していない場合、それらのユーザーのログはプロキシIPの表示に戻ってしまいます。
- **古いIPリスト:**Cloudflareは数ヶ月ごとに範囲を更新します。`https://www.cloudflare.com/ips-v4`から最新のIPを自動的に取得するスクリプトの使用を検討してください。

Related Error Notes