
High-performance WAF built on the OpenResty stack
lua-resty-waf - High-performance WAF built on the OpenResty stack
NOTE: lua-resty-waf is essentially abandoned. This project had a use in a time when ModSecurity for Nginx was not a viable option; this is no longer the case. There was an attempt to revitalize the project in 2020, but I do not have the resources to complete this; this work is partially complete in the redux branch.
lua-resty-waf is a reverse proxy WAF built using the OpenResty stack. It uses the Nginx Lua API to analyze HTTP request information and process against a flexible rule structure. lua-resty-waf is distributed with a ruleset that mimics the ModSecurity CRS, as well as a few custom rules built during initial development and testing, and a small virtual patchset for emerging threats. Additionally, lua-resty-waf is distributed with tooling to automatically translate existing ModSecurity rules, allowing users to extend lua-resty-waf implementation without the need to learn a new rule syntax.
lua-resty-waf was initially developed by Robert Paprocki for his Master's thesis at Western Governor's University.
lua-resty-waf requires several third-party resty lua modules, though these are all packaged with lua-resty-waf, and thus do not need to be installed separately. It is recommended to install lua-resty-waf on a system running the OpenResty software bundle; lua-resty-waf has not been tested on platforms built using separate Nginx source and Nginx Lua module packages.
For optimal regex compilation performance, it is recommended to build Nginx/OpenResty with a version of PCRE that supports JIT compilation. If your OS does not provide this, you can build JIT-capable PCRE directly into your Nginx/OpenResty build. To do this, reference the path to the PCRE source in the --with-pcre configure flag. For example:
# ./configure --with-pcre=/path/to/pcre/source --with-pcre-jit
You can download the PCRE source from the PCRE website. See also this blog post for a step-by-step walkthrough on building OpenResty with a JIT-enabled PCRE library.
lua-resty-waf was designed with efficiency and scalability in mind. It leverages Nginx's asynchronous processing model and an efficient design to process each transaction as quickly as possible. Load testing has show that deployments implementing all provided rulesets, which are designed to mimic the logic behind the ModSecurity CRS, process transactions in roughly 300-500 microseconds per request; this equals the performance advertised by Cloudflare's WAF. Tests were run on a reasonable hardware stack (E3-1230 CPU, 32 GB RAM, 2 x 840 EVO in RAID 0), maxing at roughly 15,000 requests per second. See this blog post for more information.
lua-resty-waf workload is almost exclusively CPU bound. Memory footprint in the Lua VM (excluding persistent storage backed by lua-shared-dict) is roughly 2MB.
A simple Makefile is provided:
# make && sudo make install
Alternatively, install via Luarocks:
# luarocks install lua-resty-waf
lua-resty-waf makes use of the OPM package manager, available in modern OpenResty distributions. The client OPM tools requires that the resty command line tool is available in your system's PATH environmental variable.
Note that by default lua-resty-waf runs in SIMULATE mode, to prevent immediately affecting an application; users who wish to enable rule actions must explicitly set the operational mode to ACTIVE.
http {
init_by_lua_block {
-- use resty.core for performance improvement, see the status note above
require "resty.core"
-- require the base module
local lua_resty_waf = require "resty.waf"
-- perform some preloading and optimization
lua_resty_waf.init()
}
server {
location / {
access_by_lua_block {
local lua_resty_waf = require "resty.waf"
local waf = lua_resty_waf:new()
-- define options that will be inherited across all scopes
waf:set_option("debug", true)
waf:set_option("mode", "ACTIVE")