If you accept connections from websites or API running behind Cloudflare, there’s a hidden “gotcha” you must know about:
By default, your end-point server will NOT see the real end-user’s IP address.
Instead, every incoming request appears to come from a Cloudflare data center.
This impacts:
- Abuse prevention (rate limiting)
- Accurate analytics
- Geo-targeting
- Any IP-based feature or logging
Why?
Cloudflare acts as a reverse proxy, routing all traffic through their global edge network.
Your server’s REMOTE_ADDR
variable now reflects the Cloudflare node—not your actual visitor.
The Solution: Use the Special HTTP Header
Cloudflare automatically sends the true client IP in the CF-Connecting-IP
HTTP header.
To reliably log and process the real user’s IP in PHP, use this snippet:
function getRealIp() {
// Prefer Cloudflare's header if present
if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
return $_SERVER['HTTP_CF_CONNECTING_IP'];
}
// Optionally support generic proxies
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
return explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0];
}
// Fallback to server-provided address
return $_SERVER['REMOTE_ADDR'] ?? 'UNKNOWN';
}
Best Practices:
- Use this
getRealIp()
helper everywhere you log, rate-limit, or analyze IP addresses. - If you use other CDNs or reverse proxies, check their docs for equivalent headers.
- Do not trust
X-Forwarded-For
unless you control all proxy hops—it can be spoofed by end users.
Why This Matters:
- Without this fix: All requests appear to originate from Cloudflare, making IP-based abuse detection and analytics impossible.
- With this fix: You’ll always have the real end-user IP, whether you’re behind Cloudflare or not.
Resources:
TL;DR:
When accounting for Cloudflare, always log and use the IP from CF-Connecting-IP
, not just REMOTE_ADDR
.
It’s a simple fix that saves hours of debugging and improves your site’s security and analytics.
Leave a Reply