This is now automated in a script and available here.
Cloudflare uses different IP ranges, and they change frequently. And to be able to show the real IP of the visitor you have to make changes to your nginx config by setting real ip, like this:
server { # Subnet from Cloudflare that is masked with mod_real_ip # Above this comment is nginx-conf-before 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 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; # Below this comment is nginx-conf-after real_ip_header X-Forwarded-For; real_ip_recursive on; listen 192.168.1.200:443 ssl; ssl on; ssl_certificate /etc/nginx/ssl/your-host.pem; ssl_certificate_key /etc/nginx/ssl/your-host.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Only use safe chiffers ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RS$ ssl_prefer_server_ciphers on; server_name your-host.com; set $upstream 192.168.1.111:443; # This config file is not complete, fyi.
The bold text is the Cloudflares different IPs, and as those changes from time to time, we figured out a way to replace them. This guide will explain how.
-
Make a backup of your original config file
$~: sudo cp /etc/nginx/sites-available/your-host.conf /etc/nginx/sites-available/your-host.conf_bak
-
Copy the content of your config before the ‘set_real_ip_from’
Copy the content to a “begin file”, in the example above we call it “nginx-conf-above”, and save it where you want. To make it easier to find, create a folder inside sites-available, and name it “your-host” i.e.
$~: sudo mkdir /etc/nginx/sites-available/cloudflare_ip/your-host
$~: sudo nano /etc/nginx/sites-available/cloudflare_ip/your-host/nginx-conf-before
Put this in that file
server { # Subnet from Cloudflare that is masked with mod_real_ip
-
Save and exit
-
Copy the content of your config after the ‘set_real_ip_from’
Do the same procedure here, copy the content to an “after file”, in the example above we call it “nginx-conf-below”, and save it to the folder you just created – “your-host”.
$~: sudo nano /etc/nginx/sites-available/cloudflare_ip/your-host/nginx-conf-after
Put this in that file
real_ip_header X-Forwarded-For; real_ip_recursive on; listen 192.168.1.200:443 ssl; ssl on; ssl_certificate /etc/nginx/ssl/your-host.pem; ssl_certificate_key /etc/nginx/ssl/your-host.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Only use safe chiffers ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RS$ ssl_prefer_server_ciphers on; server_name your-host.com; set $upstream 192.168.1.111:443; # This config file is not complete, fyi.
-
Compile the files to become a new vhost for nginx
When you got the content from your original file, then create a bash script that will compile the new config file, together with the IPs from Cloudflare and put everything into a new config file. Remember to restart Nginx for the changes to take effect, this is done in the script.
Finally let’s make a test by executing the script with bash
$~: sudo nano /etc/nginx/sites-available/cloudflare_ip/cloudflare-new-ip.sh
Put this in that file
#!/bin/bash ( cat /etc/nginx/sites-available/cloudflare_ip/your-host/nginx-conf-before ; wget -O- https://www.cloudflare.com/ips-v4 | sed 's/.*/ set_real_ip_from &;/' ; cat /etc/nginx/sites-available/cloudflare_ip/your-host/nginx-conf-after ) > /etc/nginx/sites-available/your-host.conf service nginx restart exit 1
-
Lets break it down into smaller pieces:
The before file:
( cat /etc/nginx/sites-available/cloudflare_ip/your-host/nginx-conf-before
The IP addresses from Cloudflare
wget -O- https://www.cloudflare.com/ips-v4 |
Use sed to put ‘set_real_ip_from’ before the IP from the list
sed 's/.*/ set_real_ip_from &;/'
The after file
cat /etc/nginx/sites-available/cloudflare_ip/your-host/nginx-conf-after
And everything goes in to the new nginx config file
) > /etc/nginx/sites-available/your-host.conf
Restart nginx
service nginx restart
-
Test the script
$~: sudo bash /etc/nginx/sites-available/cloudflare_ip/cloudflare-new-ip.sh
-
All done!
You can also make it a cronjob so that the IPs are updated every month if you like. But remember to make changes in the before or after file when you make changes to your new config file. All the settings you make in your regular config file will be overwritten by the script.