WordPress DDoS Attack Protection with Varnish 3 Firewall

Varnish a reverse proxy which seriously speeds up your WordPress site. If I didn't use Varnish on HTPC Guides the page load time would be 3+ seconds due to the slowness of PHP and all the WordPress plugins I use. Thankfully, I host on a Digital Ocean VPS where you can install Varnish very easily. I was recently DDoSed for the first time and wanted to use something besides Cloudflare for DDoS protection. Varnish has many firewall vmods that you can use to tweak how it responds to threats. In this tutorial I use the Throttle vmod and the Shield vmod. Throttle detects if there are too many requests per second and shield resets the connection if the request threshold has been reached. I will assume you already have Varnish 3 configured. The Varnish 4.x DDoS protection guide is here. This guide will work behind CloudFlare.

VPS Provider
Locations
RAM
Hard Drive
Speed
Price
Vultr
US, EU, Asia
768 MB
15 GB SSD
100 Mbps
$5 / month
Digital Ocean
US, EU, Asia
512 MB
20 GB SSD
100 Mbps
$5 / month
HostUS
US, UK, China, Australia
768 MB
20 GB
1-10 Gbps
$15 / year

WordPress DDoS Attack Protection with Varnish 3 Firewall

This guide uses 2 Varnish vmods to create some WordPress DDoS protection. The throttle vmod detects the number of requests and the shield vmod resets the attacker's connection.

varnish-3-cache-ddos-firewall

Install Varnish 3 and Build Varnish Source

You probably already have Varnish installed, however you will still need to execute at least the two red lines to add the source files as they are needed to build the Varnish vmods.

sudo apt-get install apt-transport-https -y
wget -O - https://repo.varnish-cache.org/GPG-key.txt | sudo apt-key add -
echo "deb https://repo.varnish-cache.org/debian/ wheezy varnish-3.0" >> /etc/apt/sources.list.d/varnish-cache.list
echo "deb-src https://repo.varnish-cache.org/debian/ wheezy varnish-3.0" >> /etc/apt/sources.list.d/varnish-cache.list
sudo apt-get update
sudo apt-get install varnish -y

Check your Varnish version

varnishd -V

If it is below 3.0.7 you will install from source on top of the repo which is an extra step after preparing the Varnish source to compile the vmods.

Prepare the Varnish source

cd ~
sudo apt-get build-dep varnish -y
sudo apt-get source varnish -y
cd varnish-3.0.7
./configure --prefix=/usr && sudo make

If you need Varnish version 3.0.7 installed because your Varnish version was not 3.0.7

make install

Also copy the updated varnishstat and varnishlog if you are installing Varnish 3.0.7 from source

sudo mv ~/varnish-3.0.7/bin/varnishstat/varnishstat /usr/bin/varnishstat
sudo mv ~/varnish-3.0.7/bin/varnishlog/varnishlog /usr/bin/varnishlog

Install Varnish vmod building dependencies

sudo apt-get install dpkg-dev pkg-config build-essential -y

Find your vmods folder which you will need for compiling so it installs vmods to the right directory

sudo find / -name vmods

I got this output

/usr/lib/i386-linux-gnu/varnish/vmods

but you should see

/usr/lib/varnish/vmods

You will need the vmods path for compiling libvmod-throttle and libvmod-shield.

Install libvmod-throttle

Install libvmod-throttle for Varnish which detects the number of requests per second the attacker is making.

Adjust your VMODDIR with the directory you found before.

cd ~
git clone https://github.com/nand2/libvmod-throttle
cd libvmod-throttle
sh autogen.sh
./configure VARNISHSRC=~/varnish-3.0.7 VMODDIR=/usr/lib/varnish/vmods/
sudo make
make install

Install libvmod-shield

Install libvmod-shield which resets the attacker's connection.

sudo apt-get install git autotools-dev automake libtool -y
cd ~
git clone https://github.com/varnish/libvmod-shield
cd libvmod-shield
sh autogen.sh
./configure VARNISHSRC=~/varnish-3.0.7 VMODDIR=/usr/lib/varnish/vmods/
sudo make
make install

Create the Varnish Rules

Open your Varnish vcl file

sudo nano /etc/varnish/default.vcl

At the top you need these lines to enable libvmod-throttle and libvmod-shield

import throttle;
import shield;

And in your sub vcl_recv section put these at the start bottom of the section. It is using throttle to detect the number of requests and if it exceeds 3 per second, a Calm down error is returned after the shield vmod resets the attacker's connection.

Initially I had some issues in admin mode but have added exceptions for admin-ajax requests. If you do notice any issues you can add the exception URL in the parentheses that contains admin-ajax.php.

Optionally you can change the error message Calm down to something else.

sub vcl_recv {

# Extracts first IP from header, works with and without CloudFlare
set req.http.X-Actual-IP = regsub(req.http.X-Forwarded-For, "[, ].*$", "");
 
#Prevent hammering on wp-login page and users doing excessive searches

if(throttle.is_allowed("ip:" + req.http.X-Actual-IP, "2req/s") > 0s && (req.url ~ "xmlrpc|wp-login.php|\?s\=")) {
	error 429 "Calm down";
	# Use shield vmod to reset connection
	shield.conn_reset();
	}

#Prevent users from making excessive POST requests that aren't for admin-ajax
if(throttle.is_allowed("ip:" + req.http.X-Actual-IP, "10req/s") > 0s && ((!req.url ~ "(xmlrpc|admin-ajax)\.php|\/wp-admin\/") && (req.request == "POST"))) {
	error 429 "Calm down";
	# Use shield vmod to reset connection
	shield.conn_reset();
		
	}
}

Test your Varnish vcl file works

varnishd -C -f /etc/varnish/default.vcl

If there were no errors then reload varnish

sudo service varnish reload

Test Varnish 3 DDoS Protection

You can use Apache benchmark, there are better tools but this illustrates that the WordPress DDoS protection with Varnish 3 works.

I used the default apache2 installation and installed apache2-tools

sudo apt-get install apache2-tools -y

If you get unable to locate package try apache2-utils

sudo apt-get install apache2-utils -y

We are going to test the web server first (Apache or nginx on port 8080 or whatever port you have set as your backend in your Varnish vcl) by simulating 100 requests with 10 concurrent connections

 ab -n 100 -c 10 localhost:8080/wp-login.php

Output will look like this and you will see 0 failed requests

Server Software:        Apache/2.2.22
Server Hostname:        localhost
Server Port:            8080

Document Path:          /
Document Length:        184 bytes

Concurrency Level:      10
Time taken for tests:   0.014 seconds
Complete requests:      100
Failed requests:        0
Non-2xx responses:      100
Total transferred:      38000 bytes
HTML transferred:       18400 bytes
Requests per second:    6902.26 [#/sec] (mean)
Time per request:       1.449 [ms] (mean)
Time per request:       0.145 [ms] (mean, across all concurrent requests)
Transfer rate:          2561.39 [Kbytes/sec] received

Repeat the test but connect to Varnish this time

ab -n 100 -c 10 localhost:80/wp-login.php

Results show 85 failed requests since the WordPress Varnish DDoS protection dropped the packets

Server Software:        Varnish
Server Hostname:        localhost
Server Port:            80

Document Path:          /
Document Length:        156589 bytes

Concurrency Level:      10
Time taken for tests:   0.098 seconds
Complete requests:      100
Failed requests:        85
   (Connect: 0, Receive: 0, Length: 85, Exceptions: 0)
Non-2xx responses:      85
Total transferred:      2910210 bytes
HTML transferred:       2860790 bytes
Requests per second:    1015.44 [#/sec] (mean)
Time per request:       9.848 [ms] (mean)
Time per request:       0.985 [ms] (mean, across all concurrent requests)
Transfer rate:          28858.96 [Kbytes/sec] received

If you want to see it in action open up a browser and point to your web site behind Varnish.
Click the refresh button like a maniac and you will see this screen (minus the logo)

varnish-3-ddos-protection-libvmod-throttle-watermarked