Skip to content

How Coraza got 10% faster in a day

First some context, I was running some benchmarks on Coraza using the OWASP Core Ruleset on Apache-Modsecurity and Coraza-Caddy and I found out the Apache implementation was 50% faster than Coraza-Caddy. That was expectable, as Modsecurity is embedded in the core of Apache using APR, but I still want Coraza to be faster than modsecurity 2 (Coraza is way faster than modsecurity 3).

A 10% performance improvement for Coraza is a big deal and the way I achieved it deserves a blog post.

To start, Seclang support what they call “Macro Expansion”, it is a templating feature that evaluates variables from expressions like %{tx.some_val}. A macro expansion can access any variable from the transaction and print it as a unique value.

Macro expansions are dynamic and the content changes from transaction to transaction, so caching them was not a solution. The old implementation evaluated each macro expression as a string and used a regular expression to find tokens and replace them, which took a lot of resources.

My solution was to transform “expandable” strings into a new Coraza feature called “Macro”, a macro can compile a string and split it into tokens of different kinds, there are two types of tokens, a “string token” and a “collection token”.

Assuming we have created the transaction variables expandable=”expandable” and tokens=”tokens”:

When a compiled Macro is “expanded” the slice of tokens will be evaluated, concating all tokens in order, when a token’s variable is not nil it will transform the token into the first value of tx.GetCollection(variables.TX).Get("expandable").

A macro can be easily implemented using the coraza.Macro API:

macro, err := coraza.NewMacro("Some expresion %{tx.value} with macros")
// we check the error
expanded := macro.Expand(someTransaction)

For the results in numbers, Macro disappeared from the profiling after being the biggest resource consumer:

And well, this is the old performance graph:

Final words

There are a lot of performance improvements I must work on, but this is a huge step of many coming.

This feature hasn’t been merged into the main branch but you can check it on https://github.com/jptosso/coraza-waf/tree/v2/optimizations

Leave a Reply

Your email address will not be published. Required fields are marked *