How to read the below:
- Skim to get an overview
- Check the right way
- Check details in the answer under
Details explaining answer with examples
title (Last one)
- There are a lot of details. As the topic can be large. Skim or read all depending on your interest.
If you don't care about the right way. And want something fast.
It's advised to go the right way. You do it once. And you get all the benefits.
If you want just something fast and works. For your need.
Check if the Cloudflare headers are forwarded to your server and available in your app. If available then you can access the value. If not available. Then you need to do server config.
The Cloudflare header is CF-Connecting-IP
To access headers in PHP you can use the below method:
// Replace XXXXXX_XXXX with the name of the header you need in UPPERCASE (and with '-' replaced by '_')
$headerStringValue = $_SERVER['HTTP_XXXXXX_XXXX'];
- Replace
XXXXXX_XXXX
with the name of the header you need in UPPERCASE (and with '-' replaced by '_')
In our case, we should check
$_SERVER['HTTP_CF_CONNECTING_IP']
You can check more ways of accessing headers here
How do I read any request header in PHP
Note: Why the right way? If there are any modules that rely on REMOTE_ADDR
variable automatically. You'll find yourself needing to go for the resolution. As they won't work. Same thing with logs. Like Apache logs. U start to see Cloudflare IPs (surely you can modify the Apache formatting to include the Cloudflare header value). However, you can get the idea. Of how many places you may need to do things if you don't go for the resolution.
Refs
Right way and Cpanel|Plesk
This will probably mean I cannot use mod_cloudflare
- (or ip-resolution modules)
No you can without any issue if you are using Apache alone as server. Or Nginx alone as a server.
If You are using Apache behind Nginx as a proxy.
Three cases:
Case 1: CPanel or Plesk already does set the headers (Which normally is the case)
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
If those two lines are there. In that case. You only need to add one newly created config
file in Nginx
. No issue at all. No conflict with Plesk or CPanel. And In Apache
the same (one file). In Apache you use X-Real-IP
.
Case 2: CPanel doesn't include X-Real-IP
But does for X-Forwarded-For
You can use X-Forwarded-For
for resolution in Apache.
Case 3: If none of those lines are included by default
(Which normally is never the case. At least X-Forwarded-For
)
In that case, you can use a hack. Where through shell scripting you check and add an include toward a config file. That injects lines inside the location {}
block in question. You can use chatgpt
for creating such a script fast. Make sure to include a check. And include the script in systemd
using ExecStartPre=
(have to run before start). So on service restart the check happens. If the include is not there it would add it. If Plesk|Cpanel ever regenerates the config after. Plesk|Cpanel will restart the service and our script will make sure to put back the include
if not there.
Real ip resolution as the right way
The right way is to set a real-ip resolution at server levels
- Nginx (with http_realip_module)
- You just add a config. As shown in the link to the answer below.
- No issue with CPanel or Plesk.
only. Clone the Plesk|Cpanel config and link to the clone directly. And take it from there.
- Apache (with mod_remoteip module)
- You just add a config. As shown in the link to the answer below.
- No issue with CPanel or Plesk.
- Or both Nginx and Apache, in a multi-proxy setup (Using both of the above)
- Nginx as a reverse proxy
- The part about passing headers to Apache (
location {}
block for proxy_pass
). Would require u to modify cpanel or plesk-generated configs. You can script a check and inject an included line within the proxy passing location block. (check the answer in the last title)
- Otherwise, u opt out of Plesk or Cpanel for Nginx config
The benefit of that. Is having the whole stack works naturally without modifications and the whole stack. Also if you make modifications to your stack. Things will remain to work without needing to re-setup.
- Apache, and all its modules
- App and framework and all libraries behind Apache
- Same thing for nginx
- The logs will work with clients' IPs. Not Cloudflare. In debugging is helfpul
- Modules relying on logs and the ip's will not get broken
- In short the whole stack. Variables are defined at every stack or layer level. And depending on the layers above them.
Also, The usage of such real-ip
modules adds trust security
.
- Only the defined trusted ips will be used to set the real-ip.
Note: Why the right way? If there are any modules that rely on REMOTE_ADDR variable automatically. You'll find yourself needing to go for the resolution. As they won't work. Same thing with logs. Like Apache logs. U start to see Cloudflare IPs (surely you can modify the Apache formatting to include the Cloudflare header value) (Then what about modules that may rely on the log format). In all cases, however, you can get the idea. Of how many places you may need to do things if you don't go for the resolution.
Cloudflare module deprecated
As by Cloudflare doc. The Old Cloudflare module is deprecated. And you have to use Apache and Nginx-specific specialized modules.
https://developers.cloudflare.com/support/troubleshooting/restoring-visitor-ips/restoring-original-visitor-ips/ a good read.
Details explaining answer with examples (all info are in the SO answer link)
My answer here shows a full example and goes into explaining the details, It's long and detailed
https://stackoverflow.com/a/76845593/7668448
Info index (points of the answer above)
- Two sides deal
- One side set headers (Proxy)
- One side resolves using the headers and set real-ip (overriding internal variables)
- Right way. Because it allows all stacks defaults to work naturally
- What does setting real-ip mean (Nginx, Apache, ....)
- Cloudflare => Nginx => Apache situation example
- Proxy side (Nginx example)
- Why we should use real-ip module
- Details about all elements
- real-ip module
- X-Forward-for header and how it works
$remote_addr
variable
$proxy_add_x_forwarded_for
variable
- X-Forwarded-For vs X-Real-IP
- Usual used Headers
- Setting headers
- Apache Side .
mod_remoteip
module
- whole details about setting up the configuration
- Setting real-ip, vs just Logging headers
- Some header debugging tips (Apache and nginx)
- Bonus: Automating trust IP lists update