• If you are still using CentOS 7.9, it's time to convert to Alma 8 with the free centos2alma tool by Plesk or Plesk Migrator. Please let us know your experiences or concerns in this thread:
    CentOS2Alma discussion

Resolved Plesk + Cloudflare - Get visitors real IP without extension

curiosul

New Pleskian
I have a server with Plesk panel installed on him and a website which reach that server through Cloudflare! Content is served by Apache and OS is Ubuntu 14.

The problem is that all logs contain Cloudflare IP address!

The solution proposed by Cloudflare guys is to install ServerShield by Cloudflare extension. The problem is that extension force me to remove the website from my Cloudflare account and add it again through that extension which I don't want. I want to keep website on my cloudflare account and the same time I want visitors real IP.

I have installed mod_cloudflare manually with success but still receive cloudflare IPs:

root@server:~# apache2ctl -M | grep cloudflare
cloudflare_module (shared)​

Do I miss something or is not possible what I want?
 
There is no HTTPD, the only cloudflare .conf file is: /etc/apache2/mods-available/cloudflare.conf and cloudflare.load

cloudflare.conf looks like the following:

Code:
<IfModule mod_cloudflare.c>
    CloudFlareRemoteIPHeader CF-Connecting-IP
    CloudFlareRemoteIPTrustedProxy 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 104.16.0.0/12 108.162.192.0/18 131.0.72.0/22
        141.101.64.0/18 162.158.0.0/15 172.64.0.0/13 173.245.48.0/20 188.114.96.0/20 190.93.240.0/20 197.234.240.0/22 198.41.128.0/17
        199.27.128.0/21 2400:cb00::/32 2606:4700::/32 2803:f800::/32 2405:b500::/32 2405:8100::/32 127.0.0.1
    #DenyAllButCloudFlare
</IfModule>
 
Solved! The Apache configuration worked correct but I forget that Nginx acted as a reverse proxy for Apache and it didn't pass to Apache correct IP!
The solutions was easy and didn't required console access!
All I have done was to add from Plesk Panel >> Domain >> Apache & nginx Settings and Cloudflare IPs into Additional nginx directives:
Code:
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 199.27.128.0/21;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;

# use any of the following two
real_ip_header CF-Connecting-IP;
#real_ip_header X-Forwarded-For;

However it have to be done for every website!

A globally solution would be to create a file called cloudflare.conf in /etc/nginx/conf.d with the same content above!
 
I added the code from this page: https://www.devside.net/wamp-server...pache-module-to-get-real-visitor-ip-addresses

Code:
<IfModule !mod_remoteip.c>
    LoadModule remoteip_module modules/mod_remoteip.so
</IfModule>

<IfModule mod_remoteip.c>
    # CloudFlare Header
    RemoteIPHeader CF-Connecting-IP
   
    # Trusted Proxy List
    # note - using RemoteIPTrustedProxy instead of RemoteIPInternalProxy
    # note - RemoteIPTrustedProxy does NOT trust Header provided private intranet addresses (local and LAN addresses)
    # note - RemoteIPInternalProxy is a security risk when using an external Proxy
   
    # CloudFlare IPv4 Address Ranges
    RemoteIPTrustedProxy 103.21.244.0/22
    RemoteIPTrustedProxy 103.22.200.0/22
    RemoteIPTrustedProxy 103.31.4.0/22
    RemoteIPTrustedProxy 104.16.0.0/12
    RemoteIPTrustedProxy 108.162.192.0/18
    RemoteIPTrustedProxy 141.101.64.0/18
    RemoteIPTrustedProxy 162.158.0.0/15
    RemoteIPTrustedProxy 172.64.0.0/13
    RemoteIPTrustedProxy 173.245.48.0/20
    RemoteIPTrustedProxy 188.114.96.0/20
    RemoteIPTrustedProxy 190.93.240.0/20
    RemoteIPTrustedProxy 197.234.240.0/22
    RemoteIPTrustedProxy 198.41.128.0/17
    RemoteIPTrustedProxy 199.27.128.0/21
   
    # CloudFlare IPv6 Address Ranges
    RemoteIPTrustedProxy 2400:cb00::/32
    RemoteIPTrustedProxy 2405:8100::/32
    RemoteIPTrustedProxy 2405:b500::/32
    RemoteIPTrustedProxy 2606:4700::/32
    RemoteIPTrustedProxy 2803:f800::/32
    RemoteIPTrustedProxy 2c0f:f248::/32
    RemoteIPTrustedProxy 2a06:98c0::/29
</IfModule>

to:

/etc/httpd/conf.d/cloudflare_remoteip.conf

And now all of the Cloudflare enabled sites log correctly. The only downside I see to this is when Cloudflare update their ranges the code will need updating
 
Solved! The Apache configuration worked correct but I forget that Nginx acted as a reverse proxy for Apache and it didn't pass to Apache correct IP!
The solutions was easy and didn't required console access!
All I have done was to add from Plesk Panel >> Domain >> Apache & nginx Settings and Cloudflare IPs into Additional nginx directives:
Code:
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 199.27.128.0/21;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;

# use any of the following two
real_ip_header CF-Connecting-IP;
#real_ip_header X-Forwarded-For;

However it have to be done for every website!

A globally solution would be to create a file called cloudflare.conf in /etc/nginx/conf.d with the same content above!

I am on a Network Solutions VPS. In the Apache & nginx Settings at the bottom there is only Additional Apache directives for HTTP and HTTPS. There is nothing there for additional directives for nginx. Anyone know what's up with that?
 
Hi David Jimenez,

There is nothing there for additional directives for nginx. Anyone know what's up with that?
This could happen, if nginx isn't enabled on your server, or if the needed components were not installed yet. Pls. consider to use the commands:

/usr/local/psa/admin/bin/nginxmng --help

To enable:
/usr/local/psa/admin/bin/nginxmng -e

To disable:
/usr/local/psa/admin/bin/nginxmng -d

To see the status:
/usr/local/psa/admin/bin/nginxmng -s
 
Hi David Jimenez,


This could happen, if nginx isn't enabled on your server, or if the needed components were not installed yet. Pls. consider to use the commands:

/usr/local/psa/admin/bin/nginxmng --help

To enable:
/usr/local/psa/admin/bin/nginxmng -e

To disable:
/usr/local/psa/admin/bin/nginxmng -d

To see the status:
/usr/local/psa/admin/bin/nginxmng -s

Thanks for the information, but we are a small company with no real internal knowledge of using Plesk command line and SSH, which is what I believe you are telling me. Is there a simpler way or do we need to find an outside expert to help us?
 
Hi David Jimenez,

you don't need further knowledge here, but you should at least be able to connect to your server over SSH ( as user "root" ). I recommend to give it a try, by using the free program "putty" - some things can't be handled over the Plesk Control Panel itself, if you administrate a server.
 
Used PuTTY and was able to log in and check the nginx help file, but when using the enable script I get the message that nginx is not installed. I asked Network Solutions how to install that, but they said they don't provide that information for free...
 
here is script you can use to auto-update Cloudflare IPs on your Plesk server running nginx

Code:
#!/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
CFTEMP=/root/cloudflare-ips.txt
curl -sS https://www.cloudflare.com/ips-v4 >$CFTEMP
curl -sS https://www.cloudflare.com/ips-v6 >>$CFTEMP
sed -i -e 's/^/set_real_ip_from /' $CFTEMP
sed -i '1ireal_ip_header CF-Connecting-IP' $CFTEMP
sed -i '/[^;] *$/s/$/;/' $CFTEMP
mv $CFTEMP /etc/nginx/conf.d/cloudflare.conf
#check if everything is OK
nginx -t && printf "Valid\n" || printf "Error\n" | grep 'Valid' &> /dev/null
if [ $? == 0 ]; then
        echo "restaring nginx"
        service nginx restart
        echo "done"
else
        echo "something is wrong"
        mv /etc/nginx/conf.d/cloudflare.conf /etc/nginx/conf.d/cloudflare.conf-error
        echo "check cloudflare.conf-error file"
fi

for example you can save it as /root/update-cloudflare-ips.sh and use cron to run it every X days
don't forget chmod 755 /root/update-cloudflare-ips.sh otherwise it won't work :)

this is for Plesk running Linux only!
 
Last edited:
here is script you can use to auto-update Cloudflare IPs on your Plesk server running nginx

Code:
#!/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
CFTEMP=/root/cloudflare-ips.txt
curl -sS https://www.cloudflare.com/ips-v4 >$CFTEMP
curl -sS https://www.cloudflare.com/ips-v6 >>$CFTEMP
sed -i -e 's/^/set_real_ip_from /' $CFTEMP
sed -i '1ireal_ip_header CF-Connecting-IP' $CFTEMP
sed -i '/[^;] *$/s/$/;/' $CFTEMP
mv $CFTEMP /etc/nginx/conf.d/cloudflare.conf
#check if everything is OK
nginx -t && printf "Valid\n" || printf "Error\n" | grep 'Valid' &> /dev/null
if [ $? == 0 ]; then
        echo "restaring nginx"
        service nginx restart
        echo "done"
else
        echo "something is wrong"
        mv /etc/nginx/conf.d/cloudflare.conf /etc/nginx/conf.d/cloudflare.conf-error
        echo "check cloudflare.conf-error file"
fi

for example you can save it as /root/update-cloudflare-ips.sh and use cron to run it every X days
don't forget chmod 755 /root/update-cloudflare-ips.sh otherwise it won't work :)

this is for Plesk running Linux only!

I found that this works except you are missing a newline character between both files.

Bash:
root@tiger:~# ./scripts/nginx_cloudflare_ips.sh
nginx: [emerg] host not found in set_real_ip_from "131.0.72.0/222400:cb00::/32" in /etc/nginx/conf.d/cloudflare.conf:16
nginx: configuration file /etc/nginx/nginx.conf test failed
something is wrong
check cloudflare.conf-error file

You can see in the error that the last IPv4 and the first IPv6 are joined.
I am not well versed in shell scripting but this fixed it:

Bash:
curl -sS https://www.cloudflare.com/ips-v4 >$CFTEMP
printf "\n" >> $CFTEMP
curl -sS https://www.cloudflare.com/ips-v6 >>$CFTEMP

There's two more things missing in my opinion:
1. The script should restore the previous file if nginx does not validate with the new one.
2. The operation result should always be sent to my email, when executing with cron.
I'll try to fix this in a few days.
 
I found that this works except you are missing a newline character between both files.

Bash:
root@tiger:~# ./scripts/nginx_cloudflare_ips.sh
nginx: [emerg] host not found in set_real_ip_from "131.0.72.0/222400:cb00::/32" in /etc/nginx/conf.d/cloudflare.conf:16
nginx: configuration file /etc/nginx/nginx.conf test failed
something is wrong
check cloudflare.conf-error file

You can see in the error that the last IPv4 and the first IPv6 are joined.
I am not well versed in shell scripting but this fixed it:

Bash:
curl -sS https://www.cloudflare.com/ips-v4 >$CFTEMP
printf "\n" >> $CFTEMP
curl -sS https://www.cloudflare.com/ips-v6 >>$CFTEMP

There's two more things missing in my opinion:
1. The script should restore the previous file if nginx does not validate with the new one.
2. The operation result should always be sent to my email, when executing with cron.
I'll try to fix this in a few days.
Got you :)

Code:
#!/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
CFTEMP=/root/cloudflare-ips.txt
curl -sS https://www.cloudflare.com/ips-v4 >$CFTEMP
printf "\n" >> $CFTEMP
curl -sS https://www.cloudflare.com/ips-v6 >>$CFTEMP
sed -i -e 's/^/set_real_ip_from /' $CFTEMP
sed -i '1ireal_ip_header CF-Connecting-IP' $CFTEMP
sed -i '/[^;] *$/s/$/;/' $CFTEMP
touch /etc/nginx/conf.d/cloudflare.conf # create an empty file if it doesn't exist 
\cp /etc/nginx/conf.d/cloudflare.conf /etc/nginx/conf.d/cloudflare.conf.bak -f # copy the old file
mv $CFTEMP /etc/nginx/conf.d/cloudflare.conf 
#check if everything is OK
nginx -t && printf "Valid\n" || printf "Error\n" | grep 'Valid' &> /dev/null
if [ $? == 0 ]; then
        echo "restaring nginx"
        service nginx restart
        echo "done"
else
        echo "something is wrong"
        mv /etc/nginx/conf.d/cloudflare.conf /etc/nginx/conf.d/cloudflare.conf-error
        cp /etc/nginx/conf.d/cloudflare.conf.bak /etc/nginx/conf.d/cloudflare.conf # restore old configuration file 
        echo "check cloudflare.conf-error file"
        printf "From: x\nTo: x\nSubject: Cloudflare File Validation Failed\ncheck cloudflare.conf-error file" | /usr/sbin/sendmail -t
fi
 
@john0001 great, thanks, I've now set it to execute on Monday @ 8:00 :)

Btw. sorry that it took me so long to respond. I did not receive any email notification regarding this.
 
Hello guys

Thanks for your inputs. Based on these inputs and the script from @peraburek and @john0001, the Plesk Support and our team created a fail-safe script for nginx which updates the IPs from Cloudflare and can be run via cronjob.

Improved in the script:
  • Added a more clear syntax
  • Added a check if the Nginx is used at the server
  • Made sure, that in case of a critical issue within the config file, it's removed and future script execution is prevented, while /etc/nginx/conf.d/cf-stop exists (it is created if for example something was changed at the Cloudflare's side)

Also, the help article regarding this topic was updated.
You can find the script here.

Hope this helps.
 
Back
Top