Guides

Load Testing a WAF

Load testing a WAF is quite similar to testing a website, with the added complexity that you may wish to test things like DoS limits, or blocked requests, etc.

A Web Application Firewall (WAF) is a security solution that can be container-based, a virtual machine, cloud offering, or hardware device. It proxies all communications between users and your website or web applications to ensure they are safe and secure.

Load testing a WAF is quite similar to testing a website, with the added complexity that you may wish to test things like DoS limits, or blocked requests, etc.

Why LoadForge

LoadForge is one of very few solutions capable of delivering a large enough quantity of traffic to actually test a WAF with real world web requests, SSL traffic, etc. It's also capable of launching a DoS attack on your WAF in order to see how it handles it (LoadForge can run up to 5 million SSL transactions per second).

Finally, it's actually affordable to do with LoadForge, and simple to set up.

Test Example (Standard WAF)

To test your WAF you should basically test your website behind the WAF, but with a few added "bad" requests to trigger blocks. You can use the LoadForge Wizard to automatically crawl your website and create a test, like I have done below. You'll notice that far more often (e.g. @task(10)) I request home pages, blog pages, etc. But also request /?test=/etc/passwd in order to trigger the WAF.

from locust import HttpUser, task, between

class QuickstartUser(HttpUser):
    wait_time = between(5, 9)

    @task(1)
    def index_page(self):
        self.client.get("/")
        self.client.get("/polyfill-c3c62534095b83a287c0.js")
        self.client.get("/component---src-pages-index-js-8652e73298c93efb59d4.js")
        self.client.get("/83ea38ffde07ac9c51711d5de8d5cbbd8705693f-0860e03ed0c4110519ef.js")
        self.client.get("/app-7878db00992a19bfd753.js")
        self.client.get("/framework-1699522cba54788f9fb6.js")
        self.client.get("/webpack-runtime-2c96c21aced2123f2be2.js")

    # Separate Pages 
    @task(10)
    def urls_0(self):
        self.client.get("/");

    @task(3)
    def urls_1(self):
        self.client.get("/blog");

    @task(5)
    def urls_2(self):
        self.client.get("/blog/checking-a-remote-hosts-ssl-expiry-date-with-php");

    @task(5)
    def urls_3(self):
        self.client.get("/blog/prevent-lazy-loading-in-laravel");

    # "Bad" Pages
    @task(1)
    def bad_pages(self):
        self.client.get("/?test=/etc/passwd");

Note that LoadForge may trigger denial of service alerts with the above test, and you may need to disable those or whitelist the networks for the location your servers are deployed.

DoS Test

A DoS test basically involves sending a large amount of traffic to your web site or application and seeing if it's possible to bring it offline. The WAF may fail, or systems behind it may. It's important your WAF can at least handle small to medium sized DoS attacks to make it costly for attackers to DoS you.

The test script for this is far simpler, we essentially just want to send a large amount of requests:

from locust import task, between
from locust.contrib.fasthttp import FastHttpUser

class MyUser(FastHttpUser):
    wait_time = between(0.1, 0.5)

    @task
    def index(self):
        response = self.client.get("/")

Now the most important part is your Test setup. You'll want to configure multiple Servers and many virtual Users. This is made easy with LoadForge, as seen in the screenshot below:

dos.png

You'll see here that we are launching 10 worker servers, and 100,000 users. You can scale this up and down as needed, but typically this will generate around 50,000-150,000 SSL requests per second which is a very large amount of load for a single WAF.

LoadForge Managed Tests

We provide managed DoS testing, WAF testing and more. Please see our managed options for more information. Alternatively, register an account today and begin your own tests.

Ready to run your test?
LoadForge is cloud-based locust.io testing.