Experimental -- not production ready.
Apache HTTPD module for the Coraza WAF engine, using libcoraza (C bindings).
Same dependency chain as coraza-nginx: coraza (Go) -> libcoraza (C bindings) -> this module.
Requires libcoraza headers at compile time and the shared library at runtime. The module is not linked against libcoraza -- it loads it via dlopen() after fork to avoid Go runtime deadlocks.
make
make install
Or with a custom apxs path:
make APXS=/path/to/apxs
Builds everything from source (libcoraza + module):
docker build --no-cache -t coraza-apache-test .
docker run --rm -d --name coraza-apache-test -p 8888:80 coraza-apache-test
./test.sh http://localhost:8888
docker stop coraza-apache-test
To test with a specific MPM (default is event):
docker build --no-cache --build-arg MPM=prefork -t coraza-test-prefork .
docker run --rm -d --name coraza-test-prefork -p 8889:80 coraza-test-prefork
./test.sh http://localhost:8889 --mpm=prefork
docker stop coraza-test-prefork
The --mpm flag verifies the server is running the expected MPM via the
server-info endpoint.
All standard modsecurity Sec* directives are registered natively, so existing
modsecurity configs (including CRS) can be used directly via Apache's Include:
LoadModule coraza_module modules/mod_coraza.so
Coraza On
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess Off
# OWASP CRS — use CorazaRulesFile so that relative data file paths
# (e.g. @pmFromFile scanners-user-agents.data) resolve correctly
CorazaRulesFile /etc/coraza/coraza-waf.conf
# Custom exclusions for a specific path
<Location /api/upload>
SecRuleRemoveById 920420
SecRequestBodyLimit 52428800
</Location>
# Disable inspection entirely for health checks
<Location /health>
Coraza Off
</Location>
# Directory-based custom rule
<Directory /var/www/uploads>
SecRule FILES_NAMES "\.php$" "id:10001,phase:2,deny,status:403"
</Directory>
# Disable via .htaccess (requires AllowOverride All)
# In .htaccess: Coraza OffSec* -- all standard modsecurity directives (SecRuleEngine, SecRule,
SecAction, SecRequestBodyAccess, SecAuditEngine, etc.) are registered
natively and can be used directly in Apache config files. Context: server config, <VirtualHost>, <Location>, <Directory>, .htaccess.
Coraza On|Off -- enable or disable the module. Context: server config, <VirtualHost>, <Location>, <Directory>, .htaccess.
CorazaRules "..." -- inline rule or directive. Context: server config, <VirtualHost>, <Location>, <Directory>, .htaccess.
CorazaRulesFile /path -- load rules from file. Use this for CRS and other rule
files that reference relative data file paths. Context: server config, <VirtualHost>, <Location>, <Directory>, .htaccess.
CorazaTransactionId "..." -- custom transaction ID. Context: server config, <VirtualHost>, <Location>, <Directory>, .htaccess.
Rules defined at server level are inherited by <VirtualHost>, <Location>, <Directory>, and .htaccess.
Setting Coraza Off in any context disables inspection for that scope.
The module hooks into Apache's request processing:
- Phase 1 (fixups hook): connection info, URI, request headers
- Phase 2 (fixups hook): request body -- read proactively via ap_get_client_block()
- Phase 3-4 (output filter): response headers and body, with header delay
- Phase 5 (log_transaction hook): audit logging
Rules are collected as strings during config parsing (master process) and replayed in each child process after dlopen. This is required because the Go runtime inside libcoraza cannot be loaded before fork.
- Tested with prefork and event MPMs
Apache License 2.0