Varnish WAF

Getting Started

Confirm ModSecurity is Installed Correctly

To test that ModSecurity is installed correctly use a simple configuration file that denies a request and a VTC that makes a few requests. For example:


This simple configuration file will block any request that has a request URL containing foo with a response code of 678.

Create a file called test.conf with the following:

SecRuleEngine On # Make sure ModSecurity is on
SecRule REQUEST_URI "/foo" "id:1, phase:1, status:678, deny"


This VTC shows what will happen when the configuration file above is loaded into ModSecurity and what happens when requests are passed through Varnish. This test contains five requests. The first two requests do not contain foo and therefore will have a response code of 200. While the last three requests contain foo in some part of the URL and will have a response code of 678.

Create a file called test.vtc with the following. Note that we need to reference the previous test.conf rule.

varnishtest "waf"

server s1 -repeat 5 {
} -start

varnish v1 -vcl+backend {
	include "waf.vcl";

	sub vcl_init {

} -start

client c1 {
	txreq -url /good
	expect resp.status == 200

	txreq -url /good1
	expect resp.status == 200

	txreq -url /foo 
	expect resp.status == 678

	txreq -url /good/foo
	expect resp.status == 678

	txreq -url /foo1
	expect resp.status == 678

} -run

Now run the test using varnishtest:

varnishtest test.vtc

WAF Configuration

The main configuration file, /etc/varnish/modsec/waf.conf should reference at least two files. The first file is the ModSecurity configuration file, modsecurity.conf. The next file is the CRS configuration file, crs-setup.conf, and optionally any combination of CRS or proprietary rule sets.

The example below includes all of the configuration files in the CRS. The path to the debug and audit logs should be edited to the ones that Varnish can read so Varnish can start correctly. To update the path to these logs, edit modsecurity.conf.

include /etc/varnish/modsec/modsecurity.conf
include /etc/varnish/modsec/owasp-crs/crs-setup.conf
include /etc/varnish/modsec/owasp-crs/rules/*.conf

VCL Configuration

Enabling Varnish WAF is as simple as adding one include statement at the top of a VCL and setting the path to main configuration file.

vcl 4.0;

include "waf.vcl";

sub vcl_init {

Remote or Proprietary Rules

It is also possible to add rules from a remote server or any other proprietary rules that are compatible with ModSecurity. If the rules are local, the configuration file will need to be added to /etc/varnish/modsec/waf.conf in the way it is described above.

If the rules are remote the rules can be added in two ways.

The first way is to use Varnish WAF directly by adding the following line to vcl_init:

varnsh_waf.add_file_remote("", "crypto_key")

The second way is by adding the ModSecurity command to the end of /etc/varnish/modsec/owasp-crs/crs-setup.conf.

SecRemoteRules crypto_key

Behind the Scenes of waf.vcl

Varnish WAF works on the backend side Varnish. Anytime that Varnish makes a request to a Backend (misses or passes), it is scanned by Varnish WAF. waf.vcl handles all aspects of the ModSecurity work flow, but there are still something that can be edited in the VCL.

waf.vcl will cache the first MB of the request body. See the API for how to increase the cached request body size.

Another option is to set the client IP and port number. This is set in the main VCL (the one that includes waf.vcl) in vcl_recv with the request headers req.http.waf-client-ip and req.http.waf-client-port. This defaults to one of two options, if there is a X-Forward-For header, the first IP is taken (with a port of 0), otherwise it will take client.ip and std.port(client.ip). Additionally any request can skip ModSecurity all together by setting the request header, req.http.waf-skip, to "true". For more information about editing these options see the API.

By default, all response bodies with a Content-Type of audio, image, or video will be skipped as scanning static content, like these three types, will waste resources. If this should be changed or other configurations are needed, see Advanced Configuration for more details.

Basic Usage and Practices

ModSecurity is a vast toolbox capable of many things, but so is Varnish. It is best practice to use Varnish in certain cases, for example, throttling or geolocation restriction. ModSecurity is fast and efficient, but the less rules that need to be parsed and acted upon, the faster a request will be. In the case like those listed above or issuing static content, using Varnish will allow you to skip ModSecurity all together getting the most performance with the same level of security.


Before going into production, it is best to see how Varnish WAF works with the current web application. There can be false positives blocking users where they should not be blocked and take up unnecessary compute resources. A method to scale down the amount of false positives is shown in the following steps:

  1. Make sure the SecRuleEngine and SecAuditEngine are set to on.
  2. In crs-setup.conf set the rule, 900110, containing the inbound and outbound anomaly thresholds to a very high number such as 1,000 to make sure all requests pass through (resulting in no little to no blocked requests).
  3. Go through the flow of the web application.
  4. Examine the audit log for false positives.
  5. Add rules producing false positives to /etc/varnish/modsec/owasp-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf with SecRuleRemoveById NUMBER.
  6. If no false positives are present, lower the anomaly thresholds and repeat these steps starting from step 3 until the thresholds are back to their default values of 5 and 4.

O’Reilly has a tutorial about limiting the amount of false positives that follows similar logic as the one described above but with some useful grep based tools to further examine the amount of false positives. Furthermore, some other tools that will help you navigate your web application looking for vulnerabilities like those in the OWASP top 10, include OWASP’s Zed Attack Proxy Protocol, Zap, and Nikito. Both of these tools are open source projects that scan and attack web applications to help fill security holes. The usage of these tools are outside of the scope of this documentation.