Skip to content

Mod Security slows down Apache if SecHashKey isn't set #1671

Closed
@monkburger

Description

@monkburger

While investigating a performance drop (10<->20% post meltdown) we noticed this line of code:

if (dcfg->crypto_key == NOT_SET_P) dcfg->crypto_key = getkey(dcfg->mp);
Which calls getkey(), which then does this:


apr_generate_random_bytes(salt, sizeof(salt));
key = apr_psprintf(mp,"%.s",(int)sizeof(salt),salt);
 
apr_sha1_init (&ctx);
apr_sha1_update (&ctx, (const char)key, strlen(key));
apr_sha1_update (&ctx, "\0", 1);
 
apr_generate_random_bytes(salt, sizeof(salt));
value = apr_psprintf(mp,"%.*s",(int)sizeof(salt),salt);

It's calling apr_generate_random_bytes() 2 times, which with APR 1.5 (an all other versions of APR) reads /dev/urandom - This seems to be read 2x for each connection to Apache.

Post meltdown, we are seeing this with a simple open()/read() of urandom:

nothing:: 44 cycles
/dev/urandom:: 38244 cycles
getrandom syscall:: 3637 cycles
rdrand raw asm:: 44 cycles
rdrand raw asm with loops:: 51 cycles
rdrand64 intrinsics::: 44 cycles

Here's some performance metrics with a server on the same LAN, over https

Requests per second:    2301.54 [#/sec] (mean)

Setting the following in modsec2.conf, ie:

SecHashKey "foobar" KeyOnly

Give the following:

Requests per second:    2671.05 [#/sec] (mean)

The bug is that mod security should use a static, session (running) key if SecHashKey == NULL from the conf, and drop the per connection getkey() to avoid a performance loss.

Another option is to use cpuid() to see if the cpu supports rdrand/rdseed, then use that as a random number generator, or better yet, use getrandom() syscall from Linux 3.17+ which is about 5 to 10x faster until APR decides to use getrandom()

Metadata

Metadata

Labels

2.xRelated to ModSecurity version 2.x

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions