No connecting IP been passed in $_SERVER

Hi,
I’ve written a script that checks connecting IP and if it doesn’t come from official CF IPs then is blocked. Works fine on about 5 sites. But I got a new site, and a few hours after I installed and tested it, suddenly all legit traffic started to be blocked, including my request from my computer. The logfile analysis shows that HTTP header HTTP_X_REMOTE_IP or HTTP_X_FORWARDED_FOR wasn’t passed. Only headers added by CF that been present are:

  • HTTP_CDN_LOOP
  • HTTP_CF_CONNECTING_IP
  • HTTP_CF_IPCOUNTRY
  • HTTP_CF_RAY
  • HTTP_CF_VISITOR

So far on other sites, the header HTTP_X_REMOTE_IP has been passed without any issue.
Any thoughts on what could happen? I have to run it again without blocking to see if it’s fixed. But still, if this is not a reliable way to get connecting IP then I can’t avoid checking for bypassing traffic, right? Any suggestions are welcome, thank you!

Where do you get the X-Remote-IP header from? It’s neither a Cloudflare header nor a “standardized” header afaik.

You should probably use REMOTE_ADDR if requests are going directly to your web-server, or, if it’s sitting behind a reverse-proxy, set the X-Forwarded-For header and use that.

There’s also an article about restoring visitor IPs:
https://support.cloudflare.com/hc/en-us/articles/200170786-Restoring-original-visitor-IPs

Hi Albert,
I’m not interested in the original visitor’s IP. I’m talking about Cloudflare’s edge server IP. My goal is to detect traffic that is bypassing Cloudflare, accessing origin by origin’s IP. I’m doing it by checking connecting IP, that is provided as a standard, or at least it’s present in all request headers, except this case I have described.

You should really just block this at your server firewall. Iptables and allow only CF IPs

1 Like

What difference it would make if still connecting IP is missing, how the server will know it’s CF edge server?

The server’s firewall knows the IP address of a TCP connection. If it’s not from the cloudflare.com/ips list, it can drop the connection.

That’s right, but I need this on PHP level. I restate my question: Is there any reason why CF’s edge server wouldn’t send HTTP_X_REMOTE_IP header? The issue I had was a bug or some settings/rules can turn off sending of this header?

Oh, now I see. Everything you’re checking shows the actual Visitor IP address since your server restores them.

I find it easier to do a general header check and look for the presence of a regular Cloudflare header, such as CF Ray or CF IP Country if I’m enabled the geo header.

For a more secure approach, you’d have to write a Worker that injected some sort of code into a Request Header and then check that. But the worker would trigger on every single request.

Other than that, I don’t see how PHP would see a Cloudflare IP address if the server is already replacing that with the visitor IP address before it gets to PHP.

Well, in my experience 99.9% of the time, the edge server’s IP is in the header as HTTP_X_REMOTE_IP, for a month since I wrote the code it worked fine. I want to know why on one occasion it failed. Now I’m actually thinking that webserver (apache) may mess it up. I will do more testing, thou wanted to know if it’s a built in CF thing or a bug or not all web servers would be able to use it.
Thanks anyway for your input! I wonder if anybody else would have a similar experience.

1 Like

If that is the case you have some additional proxy in-between Cloudflare and your webserver and that proxy adds that header.

Cloudflare never adds such a header and - as with any IP connection - you will get the address exclusively from the IP layer, respectively from wherever Apache provides it to its modules (which is what @albert already pointed out).

That header simply does not exist and I’d follow @albert’s advice.

1 Like

Checking for the presence of a CF_ header is not a reliable way to do any kind of access control. Depending on your situation, the reliable ways to ensure that only Cloudflare can talk to your Origin are:

IP tables rule to restrict access
Using Argo Tunnel to connect your origin
Using Authenticated Origin Pull with customer certificates.

If you don’t have the ability to do any of those, then you could inject a custom header using a Transform Rule, and check for it on your Origin. The header is essentially a secret password, so treat it accordingly. This is the same as the Worker solution @sdayman mentioned, but without the potential cost of Workers.

2 Likes

Great idea to use transform rules, thank you!

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.