Open bazalt opened 1 week ago
Yes you can do that. I have a similar setup with multiple hosts/domains.
See #92
See the app
arg
spoe-message coraza-req
args app=req.hdr(host),regsub("^www.",,i) id=unique-id src-ip=src src-port=src_port dst-ip=dst dst-port=dst_port method=method path=path query=query version=req.ver headers=req.hdrs body=req.body
event on-frontend-http-request
spoe-message coraza-res
args app=str(txn.app_name) id=unique-id version=res.ver status=status headers=res.hdrs body=res.body
event on-http-response
Your domain (without www) is the application.
Also featuring different configurations/exclusions with a sites.d
directory.
On
or DetectionOnly
per application (Website)You can configure different log files too.
# The SPOA server bind address
bind: 0.0.0.0:9000
# Process request and response with this application if provided app name is not found.
# You can remove or comment out this config param if you don't need "default_application" functionality.
default_application: default_haproxy
applications:
default_haproxy: &default
# Get the coraza.conf from https://github.com/corazawaf/coraza
#
# Download the OWASP CRS from https://github.com/coreruleset/coreruleset/releases
# and copy crs-custom.conf & the rules, plugins directories to /etc/coraza-spoa
directives: |
Include /etc/coraza-spoa/sites/coraza.conf
Include /etc/coraza-spoa/crs-setup.conf
Include /etc/coraza-spoa/sites/crs-custom.conf
Include /etc/coraza-spoa/sites/plugins/*-config.conf
Include /etc/coraza-spoa/sites/plugins/*-before.conf
Include /etc/coraza-spoa/rules/*.conf
Include /etc/coraza-spoa/sites/plugins/*-after.conf
Include /etc/coraza-spoa/sites/after.conf
# HAProxy configured to send requests only, that means no cache required
# NOTE: there are still some memory & caching issues, so use this with care
no_response_check: true
# The transaction cache lifetime in milliseconds (60000ms = 60s)
transaction_ttl_ms: 600000
# The maximum number of transactions which can be cached
transaction_active_limit: 100000
# The log level configuration, one of: debug/info/warn/error/panic/fatal
log_level: info
# The log file path
log_file: /var/log/coraza-spoa/coraza-agent.log
# YOUR DOMAINS HERE
example.com:
<<: *default
directives: |
Include /etc/coraza-spoa/sites.d/example.com/coraza.conf
Include /etc/coraza-spoa/crs-setup.conf
Include /etc/coraza-spoa/sites.d/example.com/crs-custom.conf
Include /etc/coraza-spoa/sites.d/example.com/plugins/*-config.conf
Include /etc/coraza-spoa/sites.d/example.com/plugins/*-before.conf
# Next line is for the default CRS Rules to load (all)
Include /etc/coraza-spoa/rules/*.conf
# Custom rules for the site
Include /etc/coraza-spoa/sites.d/example.com/rules/*.conf
Include /etc/coraza-spoa/sites.d/example.com/plugins/*-after.conf
# Adjust the log file path
log_file: /var/log/coraza-spoa/coraza-agent-example.com.log
Very clean answer, sir. Thank you very much 👍️.
Sorry to reopen this issue, but I have a complementary answer:
In HAProxy, I dynamically load backends using a txn.backend
variable:
# haproxy.cfg
[...]
frontend fe_web
[...]
http-request set-var(txn.backend) req.hdr(host),lower,map_dom(/path/to/backends.map,be_default)
#
# Apply Coraza WAF
#
# Load and apply WAF
filter spoe engine coraza config /path/to/coraza.cfg
# Currently haproxy cannot use variables to set the code or deny_status, so this needs to be manually configured here
http-request redirect code 302 location %[var(txn.coraza.data)] if { var(txn.coraza.action) -m str redirect }
http-response redirect code 302 location %[var(txn.coraza.data)] if { var(txn.coraza.action) -m str redirect }
http-request deny deny_status 403 if { var(txn.coraza.action) -m str deny }
http-response deny deny_status 403 if { var(txn.coraza.action) -m str deny }
http-request silent-drop if { var(txn.coraza.action) -m str drop }
http-response silent-drop if { var(txn.coraza.action) -m str drop }
# Deny in case of an error, when processing with the Coraza SPOA
http-request deny deny_status 504 if { var(txn.coraza.error) -m int gt 0 }
http-response deny deny_status 504 if { var(txn.coraza.error) -m int gt 0 }
use_backend %[var(txn.backend)]
I would like to reuse txn.backend
variable to load custom WAF directives, like this:
# coraza.cfg
[coraza]
spoe-agent coraza-agent
messages coraza-req
[...]
spoe-message coraza-req
# Set app name from var(txn.backend)
args app=var(txn.backend) id=unique-id src-ip=src src-port=src_port dst-ip=dst dst-port=dst_port method=method path=path query=query version=req.ver headers=req.hdrs body=req.body
event on-frontend-http-request
I tried multiple syntaxes, but for now, all of them seems to be ignored.
I resolved setting app
var by cloning from haproxy.cfg, but I'm not satisfied with this not DRY solution:
# coraza.cfg
[...]
spoe-message coraza-req
args app=req.hdr(host),lower,map_dom(/path/to/backends.map,be_default)
args id=unique-id src-ip=src src-port=src_port dst-ip=dst dst-port=dst_port method=method path=path query=query version=req.ver headers=req.hdrs body=req.body
event on-frontend-http-request
Do you know a cleaner way to achieve this? Thank you.
Hello,
I have one an only web frontend, dispatching requests to multiple backends through a host maps:
Coraza WAF is setup on this frontend, and it's working well... but I'm struggling on some use cases:
Thank you.