Nginx is awesome – really fast compared to Apache. Cloudflare is also awesome – a fast and free for most CDN.
If you are running WordPress however, there is a problem you have to deal with – namely WordPress Botnets.
Table of Contents
Countering Botnets
Cloudflare itself helps to counter a lot of bot attacks, but really if you’re serious about your site you should have fail2ban installed.
Fail2ban scans your traffic logs and based on rules you set adds IP addresses to your firewall blacklist.
This means you can stop things like XML-RPC attack vetors, login attacks and more. If you are relying on plugins like WordFence (a horror of a plugin!) or Sucuri (far better) then you are allowing bot traffic to consume your server resources. In order for Sucuri or WordFence to block attacks, the attack traffic uses NginX, PHP and MySQL resources before being stopped.
With fail2ban, this traffic is stopped before it even hits Nginx. Given the size of botnets (your site probably gets 1000 attacks per day at least), this can become a serious performance problem.
The Cloudflare Fail2ban problem
So we want to use cloudflare AND fail2ban since they both improve performance, but there’s a problem.
By default, Nginx will think your traffic is coming from the Cloudflare IP addresses. That means, fail2ban also thinks this. That means, when fail2ban bans IP addresses, if you are using Cloudflare it will ban entire groups of your customers from that Cloudflare region.
You can fix this by enabling the realip module in Nginx
Enabling realip with Nginx
To enable the realip module and fix the integration of cloudflare and fail2ban you need to do two things – first, you need to recompile nginx to have the realip module. Second you need to configure Nginx to set the realip from the cloudflare addresses.
Recompile nginx using the following on your server:
wget http://nginx.org/download/nginx-1.x.x.tar.gz tar xvzf nginx-1.x.x.tar.gz cd nginx-1.x.x ./configure --with-http_realip_module make make install
Configuring Nginx to get the real ip address from Cloudflare
Edit /etc/nginx/nginx.conf and add the following anywhere inside the http { … } area.
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;
set_real_ip_from 2c0f:f248::/32;
set_real_ip_from 2a06:98c0::/29;
real_ip_header CF-Connecting-IP;
This last line ensures the connecting IP adress is available in the $http_cf_connecting_ip variable in fail2ban.
Save the file and then edit your /etc/nginx/sites-available/* file, e.g. on the rocket stack it might be /etc/nginx/sites-available/varnish-yourdomain.com.conf. Find the main server block and see if the headers are set, if not add them, else alter:
proxy_set_header X-Real-IP $http_cf_connecting_ip;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
That ensures the IP address from the connecting ip before cloudflare is the one set as the real ip.
Allowing WordPress to see the real IP address
If you are using any plugins that rely on the originator IP address (e.g. security plugins), you can add this to your wordpress config.php file somewhere before wp-settings.php is loaded. This is an option if you don’t have fail2ban so don’t care about that possibly blocking wide swathes of cloudflare traffic instead of the single targeted IP adress.
//restore original visitor IP if from Cloudflare
if ( isset( $_SERVER[‘HTTP_CF_CONNECTING_IP’] ) ){
$_SERVER[‘REMOTE_ADDR’] = $_SERVER[‘HTTP_CF_CONNECTING_IP’];
}
Finishing Cloudflare Configuration
Now you can switch cloudflare on. If you haven’t already, you can install the Cloudflare plugin – https://en-gb.wordpress.org/plugins/cloudflare/
If you’re using W3 Total Cache, you should enable the Cloudflare add on.
Enter your Cloudflare API key into both of these plugins if you have them.
Without the plugins, cloudflare still works – but it lets you do things like bypass cloudflare (go into dev mode) directly from your site. It also lets you clear the cache etc.
Summary
Now you should have Cloudflare working nicely with fail2ban for the ultimate in performance security.
Thanks for the tutorial. For more information on how to compile nginx I found this online: https://www.vultr.com/docs/how-to-compile-nginx-from-source-on-ubuntu-16-04
I was having a hard time following the compilation instructions above because it would put nginx in /usr/local/nginx/sbin instead of /usr/sbin.
Hi Dave, and they said its support Nginx with Cloudflare: https://wordpress.org/plugins/cf-littlebizzy/
because, real IP script in the PHP plugin. thanks
Thanks – looks like a good plugin. I’ll try and get a review of it done as soon as I can.