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.

  1. 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
  2. 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
  3. Save and exit
  4. 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.
  5. 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
  6. 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
  7. Test the script
    $~: sudo bash /etc/nginx/sites-available/cloudflare_ip/cloudflare-new-ip.sh
  8. 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.


 

 pro tip

Use Cloudflare to protect your site, read more about it here.