Skip to content

corazawaf/coraza-apache

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Coraza Apache Connector

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.

Build

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

Docker

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.

Configuration example

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 Off

Directives

Sec* -- 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.

How it works

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.

Limitations

  • Tested with prefork and event MPMs

License

Apache License 2.0