WordPressのセキュリティプラグインが「IP検出の設定」について警告を出したり、PHP アプリが突然すべての訪問者を同じ数個のIPとして記録するようになったりした場合、原因はほぼ いつも同じです。Cloudflareのようなリバースプロキシが、訪問者とサーバーの間に挟まっているの です。手短に言えば、デフォルトは REMOTE_ADDR のままにし、HTTP_CLIENT_IP を無条件に信用せず、リクエストが本当にCloudflare経由で来たと 確認できたときだけ CF-Connecting-IP を読む、ということです。以下で、その一つ ひとつの理由を解説します。
各値が実際に何を意味するのか
PHPでは、これらは $_SERVER のエントリとして渡されます。これらは互換性のある ものではありません。まったく異なる出どころから来ており、その違いこそがすべての核心です。
REMOTE_ADDR— サーバーへのTCP接続を開いた相手のIPアドレスです。Webサーバーがソケットそのものから この値を埋めるため、クライアントが偽装することはできません。これが唯一信頼 できる値です。HTTP_CLIENT_IPとHTTP_X_FORWARDED_FOR— これらは通常のHTTPリクエストヘッダーです。$_SERVER内のHTTP_*エントリは、クライアントが送ってきたヘッダーにすぎません。つまり、 誰でも一行のcurlで任意の値に設定できてしまいます。HTTP_CF_CONNECTING_IP— Cloudflareが付与するCF-Connecting-IPヘッダーで、本物の訪問者IPを 含みます。リクエストがCloudflareを通過したと保証できるときのみ信頼できます。
Cloudflareの背後でREMOTE_ADDRが「間違って」見える理由
Cloudflareがあなたのドメインをプロキシすると、訪問者はCloudflareのエッジに接続し、 Cloudflareがオリジンサーバーへ新たな接続を開きます。サーバーから見ると、訪問者は Cloudflareそのものです。だから REMOTE_ADDR はCloudflareのエッジ IPになり、何千人もの別々の人に対して同じ値になります。壊れているわけではなく、プロキシが 単に役割を果たしているだけです。
本来の訪問者を渡せるよう、Cloudflareはすべてのリクエストに CF-Connecting-IP ヘッダーを付けます。したがってCloudflareの背後では、正しい取得元は $_SERVER['HTTP_CF_CONNECTING_IP'] であり、そのヘッダーが無い場合は REMOTE_ADDR にフォールバックします。
セキュリティの落とし穴:ヘッダーをそのまま信用できない理由
「HTTP_CLIENT_IP か X-Forwarded-For を読み、なければ REMOTE_ADDR」と書いて済ませたくなります。しかし、それこそがサイトを 侵害される典型的なパターンです。これらはクライアントが指定するヘッダーなので、攻撃者は 次のように送ることができます。
curl https://your-site.example/wp-login.php \
-H "X-Forwarded-For: 8.8.8.8" \
-H "Client-IP: 1.1.1.1"ログインのスロットリング、ファイアウォール、監査ログがこれらのヘッダーを読んでいると、 攻撃者はリクエストごとに偽のIPを切り替えられます。レート制限を回避し、IP バンをすり抜け、ログを汚染できてしまうのです。優れたセキュリティプラグインが検出方式を 変更する前に警告を出すのはこのためです。「より便利」な設定が、しばしば安全でない 設定なのです。
CF-Connecting-IP がこの危険から守られるのは、ある追加条件があるからにすぎ ません。オリジンがCloudflareからのトラフィックのみを受け付ける必要があるのです。 サーバーが公開IPで直接アクセスできる状態だと、攻撃者はCloudflareを飛ばして自分で CF-Connecting-IP を偽装できます。 Authenticated Origin Pulls や、CloudflareのIPレンジのみを許可するファイアウォールでオリジンを締め固めれば、この ヘッダーは信頼できるものになります。
正しい設定を、平易な言葉で
- プロキシなしの素のサーバー:
REMOTE_ADDRを使う。以上。 - Cloudflareの背後:
CF-Connecting-IP(HTTP_CF_CONNECTING_IP)を使い、ヘッダーが偽装されないようオリジンを Cloudflareに限定する。 - 別のプロキシ/CDNやロードバランサーの背後: そのプロキシが文書化して いるヘッダーを使い(多くは
X-Forwarded-Forで、右端の信頼できるホップを 取る)、やはりオリジンがそのプロキシからのトラフィックのみを受け付けるようにする。
All-In-One Security などのWordPressセキュリティプラグインでは、まさにこの選択を「IP検出」 設定が制御しています。Cloudflareの背後でない限り REMOTE_ADDR のままにし、 背後にある場合は CF-Connecting-IP に切り替えてください。
正しく設定できたか確認する方法
最も手早い動作確認は、サーバーが検出した値を、あなたの本物の公開IPと比べることです。同じ マシンから whatsmy.fyi を開いてください。外の世界からあなたがどの公開IPとして見えているかが、そのまま表示されます。 自分のアクセスに対してプラグインやアプリが記録したIPがそれと一致すれば、検出は正しく 動いています。(whatsmy.fyi自身もCloudflare上で動いているため、正しく設定されたオリジンと 同じように CF-Connecting-IP からあなたのアドレスを読み取ります。そして何も 保存しません。)
プログラムからデバッグする場合は、キー不要のエンドポイントがスクリプトに対して同じ値を 返します。
curl https://whatsmy.fyi/ip
# → your real public IP, as seen at the edge2つのIPが一致すれば、検出は正しいということです。whatsmy.fyiが本物のIPを表示している一方で サーバーがCloudflareのIPを記録しているなら、プロキシの背後でまだ REMOTE_ADDR を読んでいます。CF-Connecting-IP に切り替えてください。それ以外の形で食い違う 場合は、VPN、IPv4/IPv6の分岐、あるいは2つ目のプロキシが経路上にあります。こうしたケースに ついては、 IPが誤った位置を示す理由 についての記事で扱っています。
一行でまとめると
REMOTE_ADDR はサーバーが嘘をつかれようのない真実であり、HTTP_CLIENT_IP は誰でも言える主張にすぎません。Cloudflareの背後では CF-Connecting-IP を優先し、オリジンを締め固めて信頼性を保ったうえで、その 結果を whatsmy.fyi であなたの本物のアドレスと照合してください。


