What the check looks at
B3 compares REMOTE_ADDR, the address PHP received the request from, with CF-Connecting-IP, the visitor address Cloudflare reports. When REMOTE_ADDR is private (loopback, a local network, CGNAT or IPv6 ULA) and differs from the visitor address, something on the server stands between Cloudflare and WordPress.
The two must differ: a mobile visitor behind a carrier’s NAT can have a CGNAT address, and when that same address reaches PHP it was restored correctly, which is a pass in check B1.
Like every request Edge Doctor sends, these go only to the hosts of your Site Address and WordPress Address (home_url() and site_url()). An address WordPress gives on another host, such as a single sign on page, is never requested.
Results and what they mean
| Result | What it means |
|---|---|
| WarningConfidence: Medium | Something sits between Cloudflare and WordPress WordPress sees a private address. When check A1 found a Tunnel, the result explains that the Tunnel is the hop to carry the address across. |
| Not applicable | No local proxy or tunnel found in front of your server Reason not_observed. This is the normal result. |
| Could not checkConfidence: Low | This check could not be completed No request with Cloudflare headers could be read. |
| Not applicable | Cloudflare is not in front of this site Check A1 did not detect Cloudflare, so this check sent no request. Reason not_behind_cloudflare. |
When the result names a reason
not_observed: The plugin has not seen this happen on your site.token_missing: The test request never reached your server, so there was nothing to compare.no_snapshot: This check needs a recent visit through Cloudflare. Open the Edge Doctor report once and it will have one.qs_ignored: Your cache key ignores the query string, so the plugin cannot test a page without risking a cached copy of it. Before it asks for any private address, the plugin requests your home page twice with a different unique query string. If either answer is aHIT, your cache key ignores the query string, and a test request could store a private page under an address visitors use. So the plugin stops and sends nothing.not_behind_cloudflare: This site is not behind Cloudflare.
Symptoms you may notice
- Every comment, order and log line shows 127.0.0.1 or another private address.
- Security plugins treat all visitors as one, so a block or a login limit hits everybody.
Why it happens
A reverse proxy on the server (for example Nginx in front of Apache, or the proxy of a container setup) or cloudflared running a Tunnel opens its own connection to the web server. Unless it passes the visitor address on and the web server trusts it from that proxy, PHP sees the proxy.
Confirm it by hand
Compare your address from https://example.com/cdn-cgi/trace (the ip= line) with what your server recorded for the same visit. A private address in the log confirms it.
How to fix it
On the server: make the local proxy pass the visitor address on, and make the web server trust that header only from the proxy’s own address. With Cloudflare in front, the header that carries the visitor is CF-Connecting-IP; the Apache and Nginx settings are in the guide for check B1, with the proxy’s address as the trusted one.
In Cloudflare: nothing to change. A Tunnel means the server has no public entrance of its own for the website, which is worth keeping.
In WordPress: avoid code that trusts forwarded headers from any address.
Limitations
B3 reads one request. It cannot name the proxy, only that one is there.
Related checks
- B1 Real visitor IP not restored: the same question when no proxy is involved.
- A1 Cloudflare detection and connection type: whether the site uses a Tunnel.
- F2 DNS records revealing your server: DNS records that reveal the server.
Sources
Run this check on your own site with Edge Doctor for Cloudflare®, free on WordPress.org.
Edge Doctor for Cloudflare® is not affiliated with or endorsed by Cloudflare, Inc. Cloudflare is a registered trademark of Cloudflare, Inc.