When you have a website behind the CloudFlare DNS (using its CDN services), chances are your nginx access logs are logging CloudFlare IP addresses. This is due to the fact that your are serving content where CloudFlare acts as proxy. To log the visitor’s real IP address, you need to modify some configuration or even rebuild nginx for that purpose.
To rebuild or not?
nginx
has a module called HttpRealipModule where it allows setting real IP address for a given source IP by using the standard header values passed by proxy servers. This will allow us to tell nginx to pickup CloudFlare’s CF-Connecting-IP
header value and use it as the real IP address and will be used when logging to access logs.
This feature requires that nginx is built with --with-http-realip_module
build option. My current version is nginx 1.4.0 and luckily it has enabled --with-http-realip_module
by default.
Since the CloudFlare documentation includes ipv6 IP addresses, we also need to ensure that our nginx can handle ipv6. This requires --with-ipv6
option when building nginx. Unfortunately, my nginx is not built with ipv6 support. I am forced to rebuild it. Luckily, I’m using Slackbuilds.org’s nginx Slackbuild script. I just edited the script to pass --with-ipv6
and re-installed nginx.
HttpRealipModule
This is the guide I used when setting up the CloudFlare real ip sniff. I’ve created a file called /etc/nginx/cloudflare-real-ip.conf
.
# Cloudflare set_real_ip_from 204.93.240.0/24; set_real_ip_from 204.93.177.0/24; set_real_ip_from 199.27.128.0/21; set_real_ip_from 173.245.48.0/20; 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 141.101.64.0/18; set_real_ip_from 108.162.192.0/18; set_real_ip_from 190.93.240.0/20; set_real_ip_from 188.114.96.0/20; set_real_ip_from 197.234.240.0/22; set_real_ip_from 198.41.128.0/17; 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; real_ip_header CF-Connecting-IP;
Next, for all sites in your server that is CloudFlare enabled, include this config by putting a line in your vhost configuration like below:
server { # Some config # ... # ... # CloudFlare config include /etc/nginx/cloudflare-real-ip.conf; }
Restart nginx and what your access logs. It should start logging real IP address from now on. Be sure to update the list of IP addresses from time to time since CloudFlare may add/remove IP address in the future.
Note: We didn’t actually configured nginx to allow ipv6, but instead we just make sure that our config syntax will work and not throw error. Without the ipv6 option, our config above will fail since it will not be able to understand the ipv6 syntax. However, we didn’t specifically mentioned how to allow ipv6 connections to nginx. This requires another configuration that I am not interested as of this time.
Thank you for the tutorial. Don’t know if this is new but with the latest nGINX version, you need to add a semicolon after the include statement. Otherwise, nGINX won’t start.
# CloudFlare config
include /etc/nginx/cloudflare-real-ip.conf;
That’s correct. I missed the semi-colon when I typed it, for sure nginx would not start and I’ve experienced that a lot.
I’ve updated the post now.
Thanks