NGINX Web Application Firewall


For a long time I looked for a WAF (Web Application Firewall) for my nginx installations. As a systems administrator that installs web applications from developer teams with very different degrees of attention to security, a WAF is a must in every installation.

Why to use a WAF?

Installing a WAF helps to frustrate attack attempts. It will prevent the exploitation of some vulnerabilities present in the underlying web application and also discourage some lazy attackers who will prefer to switch to an easier target. You might even save some bandwidth from deterring these attacks.

However, a WAF is not a fix for web vulnerabilties so if you know your web application has security issues, you must fix them. Installing a WAF will certainly obstruct the exploitation, but in the long run your website will be compromised.


There are several options for securing our nginx.

We can use naxsi, however it requires some "training" to find the rules that we must whitelist and this might be a long process and it is very specific to each installation. I prefer an easy configurable WAF that it just works after it is installed.

We can also use mod_securty for nginx, but we would need to compile it specifically for our installations and take care of its maintenance each time we update nginx so it is not very practical.

There are some other custom options using ngx_lua but none of them was exactly what I wanted. However, I was inspired by them and I ended up writing my own WAF.

I wanted it to be configurable and have options to whitelist rules and IPs. I also wanted it to be fast, so ngx_lua looked like a great option.

This is why I created nginx_waf:

I've been using it for more than a year now and it has certainly blocked a ton of attacks, which can be seeing in its log file. I am very happy with the results and I plan to continue to improve it.

Please, feel free to use it and sent questions or requests via the GitHub issue tracker. All the information regarding how to use it and install it is in the repository.