Coraza SPOA is a system daemon which brings the Coraza Web Application Firewall (WAF) as a backing service for HAProxy. It is written in Go, Coraza supports ModSecurity SecLang rulesets and is 100% compatible with the OWASP Core Rule Set v4.
HAProxy includes a Stream Processing Offload Engine SPOE to offload request processing to a Stream Processing Offload Agent (SPOA). Coraza SPOA embeds the Coraza Engine, loads the ruleset and filters http requests or application responses which are passed forwarded by HAProxy for inspection.
The command go run mage.go build
will compile the source code and produce the executable file coraza-spoa
.
The example configuration file is example/coraza-spoa.yaml, you can copy it and modify the related configuration information. You can start the service by running the command:
coraza-spoa -f /etc/coraza-spoa/coraza-spoa.yaml
You will also want to download & extract the OWASP Core Ruleset (version 4+ supported) to the /etc/coraza-spoa
directory.
Configure HAProxy to exchange messages with the SPOA. The example SPOE configuration file is coraza.cfg, you can copy it and modify the related configuration information. Default directory to place the config is /etc/haproxy/coraza.cfg
.
# /etc/haproxy/coraza.cfg
spoe-agent coraza-agent
...
use-backend coraza-spoa
spoe-message coraza-req
args app=str(sample_app) id=unique-id src-ip=src ...
event on-frontend-http-request
The application name from config.yaml
must match the app=
name.
The backend defined in use-backend
must match a haproxy.cfg
backend which directs requests to the SPOA daemon reachable via 127.0.0.1:9000
.
Instead of the hard coded application name str(sample_app)
you can use some HAProxy variables. For example, frontend name fe_name
.
Configure HAProxy with a frontend, which contains a filter
statement to forward requests to the SPOA and deny based on the returned action. Also add a backend section, which is referenced by use-backend in coraza.cfg
.
# /etc/haproxy/haproxy.cfg
frontend web
filter spoe engine coraza config /etc/haproxy/coraza.cfg
...
http-request deny deny_status 403 hdr waf-block "request" if { var(txn.coraza.action) -m str deny }
...
backend coraza-spoa
mode tcp
server s1 127.0.0.1:9000
A comprehensive HAProxy configuration example can be found in example/haproxy/coraza.cfg.
Because, in the SPOE configuration file (coraza.cfg), we declare to use the backend coraza-spoa to communicate with the service, so we need also to define it in the HAProxy file:
- Build the coraza-spoa image
cd ./example ; docker compose build
- Run haproxy, coraza-spoa and a mock server
docker compose up
- Perform a request which gets blocked by the WAF:
curl http://localhost:4000/\?x\=/etc/passwd