How to Configure Nginx with Cloudflare, Cloudfront & Incapsula
Nginx Cloudflare, AWS Cloudfront, Incapsula & PageSpeed IP addresses:
Note: you may need to whitelist the IP addresses for the proxy in CSF Firewall for Cloudflare. For Cloudflare to prevent IP leaks you also want to enable Cloudflare Authenticated Origin Pull certificates on your Cloudflare Full SSL enabled sites.
If you use Cloudflare, AWS Cloudfront, Incapsula.com, Google PageSpeed Service or any reverse proxy in front of Nginx (Varnish cache, PageSpeed service, Cloud DDOS proxy etc), you will need to use Nginx's ngx_http_realip_module module which is compiled by default for Centmin Mod installs and set the set_real_ip_from and real_ip_header to properly allow Nginx to see the visiting user's real IP address and not the IP address of the reverse proxy or Cloudflare system.
Nginx Cloudflare IP addresses:
Cloudflare KB explains this here and maintains an updated list of Cloudflare IP addresses here. They also have a detailed list of article outlined here.
To use Cloudflare or a reverse proxy in front of Nginx you will need to add the following code to /usr/local/nginx/conf/nginx.conf in the http {} section if all sites on server are protected under Cloudflare. Or for specific domains and sites on server, in their domain name's Nginx vhost file which is being served via Cloudflare i.e. /usr/local/nginx/conf/conf.d/newdomain.com.conf within the server { } context. Then restart Nginx web server.
If using Centmin Mod 123.08stable or lower, see further below for manual setup instructions. If using Centmin Mod 123.09beta01 or newer branches, the generated Nginx vhost already have setup automated script to pull latest Cloudflare IPs for CSF Firewall whitelisting outlined here. The generated Nginx vhost will have an include file /usr/local/nginx/conf/cloudflare.conf that is prepopulated with Cloudflare IPs pulled in via a cronjob you manually setup as outlined here.
# uncomment cloudflare.conf include if using cloudflare for # server and/or vhost site include /usr/local/nginx/conf/cloudflare.conf;
cronjob you manually setup
23 */36 * * * /usr/local/src/centminmod/tools/csfcf.sh auto >/dev/null 2>&1
Cloudflare IPs as at March 27th, 2018. A updated list of Cloudflare IP addresses here
For Cloudflare IPv4 addresses:
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; real_ip_header CF-Connecting-IP;
For Cloudflare IPv6 addresses: (Note: not entirely sure these are correct for IPv6).
# Cloudflare set_real_ip_from 2400:cb00::/32; set_real_ip_from 2405:8100::/32; set_real_ip_from 2405:b500::/32; set_real_ip_from 2606:4700::/32; set_real_ip_from 2803:f800::/32; set_real_ip_from 2c0f:f248::/32; set_real_ip_from 2a06:98c0::/29; real_ip_header CF-Connecting-IP;
If you'd combining both IPv4 and IPv6 it's the below format with only one real_ip_header CF-Connecting-IP; instance. Add the following code to /usr/local/nginx/conf/nginx.conf in the http {} section and/or any other domain name's Nginx vhost file which is being served via Cloudflare i.e. /usr/local/nginx/conf/conf.d/newdomain.com.conf within the server { } context. Then restart Nginx web server.
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 2400:cb00::/32; #set_real_ip_from 2405:8100::/32; #set_real_ip_from 2405:b500::/32; #set_real_ip_from 2606:4700::/32; #set_real_ip_from 2803:f800::/32; #set_real_ip_from 2c0f:f248::/32; #set_real_ip_from 2a06:98c0::/29; real_ip_header CF-Connecting-IP;
For a typical reverse proxy i.e. haproxy load balancer which Centminmod.com site uses:
set_real_ip_from yourreverseproxyip; real_ip_header X-Forwarded-For;
Full context examples below:
For Cloudflare:
user nginx nginx; worker_processes 1; worker_rlimit_nofile 51200; error_log logs/error.log; pid logs/nginx.pid; events { worker_connections 32768; use epoll; } http { # Cloudflare 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; real_ip_header CF-Connecting-IP; index index.php index.html index.htm; include mime.types; default_type application/octet-stream;
For a typical reverse proxy i.e. haproxy load balancer which Centminmod.com site uses:
user nginx nginx; worker_processes 1; worker_rlimit_nofile 51200; error_log logs/error.log; pid logs/nginx.pid; events { worker_connections 32768; use epoll; } http { set_real_ip_from yourreverseproxyip; real_ip_header X-Forwarded-For; index index.php index.html index.htm; include mime.types; default_type application/octet-stream;
You can also use Nginx include file to make editing easier i.e. add the settings to /usr/local/nginx/conf/csfips.conf
you create and include it.
user nginx nginx; worker_processes 1; worker_rlimit_nofile 51200; error_log logs/error.log; pid logs/nginx.pid; events { worker_connections 32768; use epoll; } http { include /usr/local/nginx/conf/csfips.conf; index index.php index.html index.htm; include mime.types; default_type application/octet-stream;
with contents of:
# Cloudflare 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; real_ip_header CF-Connecting-IP;
Save the Nginx vhost file and then restart Nginx server
service nginx restart
or via command line shortcut
ngxrestart
Nginx AWS Cloudfront IP addresses:
Amazon AWS Cloudfront lists it's IP Ranges at https://docs.aws.amazon.com/general/latest/gr/aws-ip-ranges.html. They seem to only use IPv4 IP ranges for AWS Cloudfront service so there are no IPv6 IPs to deal with.
For Amazon AWS Cloudfront IPv4 addresses:
To grab the list of IPv4 IP ranges for Amazon AWS Cloudfront, you can use jq
tool which you can use yum -y install jq
if it's missing on your service.
First download the ip-ranges.json file via wget to a directory of your choice.
wget -4 https://ip-ranges.amazonaws.com/ip-ranges.json -O ip-ranges.json
Within that directory you saved ip-ranges.json to, you can use jq
tool to filter what you need.
Services listing which groups Amazon AWS IP range listings by service type. The service we are interested in is Cloudfront only.
cat ip-ranges.json | jq -r '.prefixes[] | .service' | sort | uniq
cat ip-ranges.json | jq -r '.prefixes[] | .service' | sort | uniq AMAZON AMAZON_CONNECT API_GATEWAY CLOUD9 CLOUDFRONT CODEBUILD DYNAMODB EC2 EC2_INSTANCE_CONNECT GLOBALACCELERATOR ROUTE53 ROUTE53_HEALTHCHECKS ROUTE53_HEALTHCHECKS_PUBLISHING S3 WORKSPACES_GATEWAYS
Only list the full AWS Cloudfront service json entries
cat ip-ranges.json | jq -r '.prefixes[] | select(.service=="CLOUDFRONT")'
small sample display output
cat ip-ranges.json | jq -r '.prefixes[] | select(.service=="CLOUDFRONT")' { "ip_prefix": "52.78.247.128/26", "region": "ap-northeast-2", "service": "CLOUDFRONT", "network_border_group": "ap-northeast-2" } { "ip_prefix": "52.220.191.0/26", "region": "ap-southeast-1", "service": "CLOUDFRONT", "network_border_group": "ap-southeast-1" } { "ip_prefix": "34.232.163.208/29", "region": "us-east-1", "service": "CLOUDFRONT", "network_border_group": "us-east-1" }
Only list Amazon AWS Cloudfront IP ranges
cat ip-ranges.json | jq -r '.prefixes[] | select(.service=="CLOUDFRONT") | .ip_prefix'
cat ip-ranges.json | jq -r '.prefixes[] | select(.service=="CLOUDFRONT") | .ip_prefix' 144.220.0.0/16 52.124.128.0/17 54.230.0.0/16 54.239.128.0/18 52.82.128.0/19 99.84.0.0/16 204.246.172.0/24 54.239.192.0/19 70.132.0.0/18 13.32.0.0/15 205.251.208.0/20 13.224.0.0/14 13.35.0.0/16 204.246.164.0/22 204.246.168.0/22 71.152.0.0/17 216.137.32.0/19 205.251.249.0/24 99.86.0.0/16 52.46.0.0/18 52.84.0.0/15 204.246.173.0/24 130.176.0.0/16 205.251.200.0/21 204.246.174.0/23 64.252.128.0/18 205.251.254.0/24 143.204.0.0/16 205.251.252.0/23 204.246.176.0/20 13.249.0.0/16 54.240.128.0/18 205.251.250.0/23 52.222.128.0/17 54.182.0.0/16 54.192.0.0/16 13.124.199.0/24 34.226.14.0/24 52.15.127.128/26 35.158.136.0/24 52.57.254.0/24 18.216.170.128/25 13.52.204.0/23 13.54.63.128/26 13.59.250.0/26 13.210.67.128/26 35.167.191.128/26 52.47.139.0/24 52.199.127.192/26 52.212.248.0/26 52.66.194.128/26 13.113.203.0/24 99.79.168.0/23 34.195.252.0/24 35.162.63.192/26 34.223.12.224/27 52.56.127.0/25 34.223.80.192/26 13.228.69.0/24 34.216.51.0/25 3.231.2.0/25 54.233.255.128/26 18.200.212.0/23 64.252.64.0/18 52.52.191.128/26 3.234.232.224/27 52.78.247.128/26 52.220.191.0/26 34.232.163.208/29
Now to get the Amazon AWS Cloudfront service only IP ranges and manipulate the IP ranges into Nginx real IP set_real_ip_from format
cat ip-ranges.json | jq -r '.prefixes[] | select(.service=="CLOUDFRONT") | .ip_prefix' | while read i; do echo "set_real_ip_from ${i};"; done; echo "real_ip_header X-Forwarded-For;"
resulting output set_real_ip_from output
cat ip-ranges.json | jq -r '.prefixes[] | select(.service=="CLOUDFRONT") | .ip_prefix' | while read i; do echo "set_real_ip_from ${i};"; done; echo "real_ip_header X-Forwarded-For;" set_real_ip_from 144.220.0.0/16; set_real_ip_from 52.124.128.0/17; set_real_ip_from 54.230.0.0/16; set_real_ip_from 54.239.128.0/18; set_real_ip_from 52.82.128.0/19; set_real_ip_from 99.84.0.0/16; set_real_ip_from 204.246.172.0/24; set_real_ip_from 54.239.192.0/19; set_real_ip_from 70.132.0.0/18; set_real_ip_from 13.32.0.0/15; set_real_ip_from 205.251.208.0/20; set_real_ip_from 13.224.0.0/14; set_real_ip_from 13.35.0.0/16; set_real_ip_from 204.246.164.0/22; set_real_ip_from 204.246.168.0/22; set_real_ip_from 71.152.0.0/17; set_real_ip_from 216.137.32.0/19; set_real_ip_from 205.251.249.0/24; set_real_ip_from 99.86.0.0/16; set_real_ip_from 52.46.0.0/18; set_real_ip_from 52.84.0.0/15; set_real_ip_from 204.246.173.0/24; set_real_ip_from 130.176.0.0/16; set_real_ip_from 205.251.200.0/21; set_real_ip_from 204.246.174.0/23; set_real_ip_from 64.252.128.0/18; set_real_ip_from 205.251.254.0/24; set_real_ip_from 143.204.0.0/16; set_real_ip_from 205.251.252.0/23; set_real_ip_from 204.246.176.0/20; set_real_ip_from 13.249.0.0/16; set_real_ip_from 54.240.128.0/18; set_real_ip_from 205.251.250.0/23; set_real_ip_from 52.222.128.0/17; set_real_ip_from 54.182.0.0/16; set_real_ip_from 54.192.0.0/16; set_real_ip_from 13.124.199.0/24; set_real_ip_from 34.226.14.0/24; set_real_ip_from 52.15.127.128/26; set_real_ip_from 35.158.136.0/24; set_real_ip_from 52.57.254.0/24; set_real_ip_from 18.216.170.128/25; set_real_ip_from 13.52.204.0/23; set_real_ip_from 13.54.63.128/26; set_real_ip_from 13.59.250.0/26; set_real_ip_from 13.210.67.128/26; set_real_ip_from 35.167.191.128/26; set_real_ip_from 52.47.139.0/24; set_real_ip_from 52.199.127.192/26; set_real_ip_from 52.212.248.0/26; set_real_ip_from 52.66.194.128/26; set_real_ip_from 13.113.203.0/24; set_real_ip_from 99.79.168.0/23; set_real_ip_from 34.195.252.0/24; set_real_ip_from 35.162.63.192/26; set_real_ip_from 34.223.12.224/27; set_real_ip_from 52.56.127.0/25; set_real_ip_from 34.223.80.192/26; set_real_ip_from 13.228.69.0/24; set_real_ip_from 34.216.51.0/25; set_real_ip_from 3.231.2.0/25; set_real_ip_from 54.233.255.128/26; set_real_ip_from 18.200.212.0/23; set_real_ip_from 64.252.64.0/18; set_real_ip_from 52.52.191.128/26; set_real_ip_from 3.234.232.224/27; set_real_ip_from 52.78.247.128/26; set_real_ip_from 52.220.191.0/26; set_real_ip_from 34.232.163.208/29; real_ip_header X-Forwarded-For;
You can also use Nginx include file to make editing easier i.e. add the resulting set_real_ip_from output to /usr/local/nginx/conf/cloudfront_ips.conf
you create and include it in your Nginx vhost config file like you do for Cloudflare include file /usr/local/nginx/conf/csfips.conf
outlined above.
So you can pipe the resulting set_real_ip_from output into to /usr/local/nginx/conf/cloudfront_ips.conf
using command
( cat ip-ranges.json | jq -r '.prefixes[] | select(.service=="CLOUDFRONT") | .ip_prefix' | while read i; do echo "set_real_ip_from ${i};"; done; echo "real_ip_header X-Forwarded-For; " ) > /usr/local/nginx/conf/cloudfront_ips.conf
include it in your Nginx vhost domain config file i.e. /usr/local/nginx/conf/conf.d/newdomain.com.conf within the server { } context.
include /usr/local/nginx/conf/cloudfront_ips.conf;
Nginx Incapsula IP addresses:
Incapsula.com explains there IP ranges here.
For Incapsula IPv4 addresses:
# Incapsula set_real_ip_from 199.83.128.0/21; set_real_ip_from 198.143.32.0/19; set_real_ip_from 149.126.72.0/21; set_real_ip_from 103.28.248.0/22; set_real_ip_from 45.64.64.0/22; set_real_ip_from 185.11.124.0/22; set_real_ip_from 192.230.64.0/18; set_real_ip_from 107.154.0.0/16; set_real_ip_from 2a02:e980::/29; real_ip_header X-Forwarded-For;
Nginx Google PageSpeed Service IP addresses:
Google also explains this in their Google PageSpeed Service FAQ. They don't provide a convenient list of IP addresses though, you have to do some work as explained in 'Google's IP addresses' page. When you run the nslookup commands on that page you get first the list of netblocks then the list of Google IP addresses from each of those netblocks like below.
For Centmin Mod users, first install bind-utils YUM package which contains nslookup command.
yum -q -y install bind-utils
Then run commands:
nslookup -q=TXT _spf.google.com 8.8.8.8 nslookup -q=TXT _netblocks.google.com 8.8.8.8 nslookup -q=TXT _netblocks2.google.com 8.8.8.8 nslookup -q=TXT _netblocks3.google.com 8.8.8.8
Which output the following:
nslookup -q=TXT _spf.google.com 8.8.8.8 Server: 8.8.8.8 Address: 8.8.8.8#53 Non-authoritative answer: _spf.google.com text = "v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all" Authoritative answers can be found from:
nslookup -q=TXT _netblocks.google.com 8.8.8.8 Server: 8.8.8.8 Address: 8.8.8.8#53 Non-authoritative answer: _netblocks.google.com text = "v=spf1 ip4:64.18.0.0/20 ip4:64.233.160.0/19 ip4:66.102.0.0/20 ip4:66.249.80.0/20 ip4:72.14.192.0/18 ip4:74.125.0.0/16 ip4:108.177.8.0/21 ip4:173.194.0.0/16 ip4:207.126.144.0/20 ip4:209.85.128.0/17 ip4:216.58.192.0/19 ip4:216.239.32.0/19 ~all" Authoritative answers can be found from:
nslookup -q=TXT _netblocks2.google.com 8.8.8.8 Server: 8.8.8.8 Address: 8.8.8.8#53 Non-authoritative answer: _netblocks2.google.com text = "v=spf1 ip6:2001:4860:4000::/36 ip6:2404:6800:4000::/36 ip6:2607:f8b0:4000::/36 ip6:2800:3f0:4000::/36 ip6:2a00:1450:4000::/36 ip6:2c0f:fb50:4000::/36 ~all" Authoritative answers can be found from:
nslookup -q=TXT _netblocks3.google.com 8.8.8.8 Server: 8.8.8.8 Address: 8.8.8.8#53 Non-authoritative answer: _netblocks3.google.com text = "v=spf1 ip4:172.217.0.0/19 ip4:108.177.96.0/19 ~all" Authoritative answers can be found from:
Take the ipv4 (and ipv6 ips if you use ipv6) from Non-authoritative answer section to form the list of Google PageSpeed Service's IP address list and add real_ip_header X-Forwarded-For; line to complete what is required for Nginx configuration. Then add the following code to /usr/local/nginx/conf/nginx.conf in the http {} section. Then restart Nginx web server.
For Google PageSpeed Service IPv4 addresses:
# Google IPs IPv4 set_real_ip_from 64.18.0.0/20; set_real_ip_from 64.233.160.0/19; set_real_ip_from 66.102.0.0/20; set_real_ip_from 66.249.80.0/20; set_real_ip_from 72.14.192.0/18; set_real_ip_from 74.125.0.0/16; set_real_ip_from 108.177.8.0/21; set_real_ip_from 173.194.0.0/16; set_real_ip_from 207.126.144.0/20; set_real_ip_from 209.85.128.0/17; set_real_ip_from 216.58.192.0/19; set_real_ip_from 216.239.32.0/19; set_real_ip_from 172.217.0.0/19; set_real_ip_from 108.177.96.0/19; real_ip_header X-Forwarded-For;
For Google PageSpeed Service IPv6 addresses:
# Google IPs IPv6 set_real_ip_from 2001:4860:4000::/36; set_real_ip_from 2404:6800:4000::/36; set_real_ip_from 2607:f8b0:4000::/36; set_real_ip_from 2800:3f0:4000::/36; set_real_ip_from 2a00:1450:4000::/36; set_real_ip_from 2c0f:fb50:4000::/36; real_ip_header X-Forwarded-For;