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.

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.

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)