Often when implementing customised ModSecurity solutions we need to extend the built-in functionality via Lua scripting. One of the disadvantages to this approach is the added latency penalty paid for not using the native rules language. When web site performance is critical for business continuity, every additional millesecond counts. The current trunk code fixes a long-standing limitation where ModSecurity needed to create a new VM for each request, which added latency every time a Lua script was executed. By combining the new Lua VM implementation along with replacing the Lua interperter with LuaJIT we can enjoy a significant speed increase in script execution.To measure the speed difference we will test with a simple script used to generate a random token as part of a predictable session token patch. The code is below:
#!/usr/bin/lua
function main()
-- Create random cookie value
local ip = m.getvar("REMOTE_ADDR")
local md5 = require "md5"
math.randomseed( os.time() )
randomtoken = md5.sumhexa(ip .. math.random())
m.log(3, "RandomToken: " .. randomtoken);
m.setvar("TX.token", randomtoken);
return 1
end
If we run this script 1000 times via the ModSecurity 2.6.2 engine, the script takes an average of 616 microseconds to run, as shown below: lab@lab:~$ for i in `seq 1 1000`; do wget -qO /dev/null http://localhost/; done
lab@lab:~$ let sum=0;for duration in
$(grep "Script completed in " /opt/modsecurity/var/log/debug.log|
cut -d " " -f 8); { let sum=$sum+$duration; };
let average=$sum/1000;echo $average
616
As noted above we can significantly increase the speed execution by using the latest engine from trunk along with using LuaJIT instead of the regular Lua shared library. The good news is setting this up is simple. As noted here as of Lua 5.1 "LuaJIT is also fully ABI-compatible to Lua 5.1 at the linker/dynamic loader level. This means you can compile a C module against the standard Lua headers and load the same shared library from either Lua or LuaJIT." In other words, all we need to do to use LuaJIT with ModSecurity is to load the LuaJIT shared library in the Apache ModSecurity module configuration. On a Debian Sid based system this looks like: lab@lab:~$ cat /etc/apache2/mods-enabled/modsecurity.load
# Load libxml2
LoadFile /usr/lib/libxml2.so
# Load Lua
LoadFile /usr/lib/x86_64-linux-gnu/libluajit-5.1.so.2.0.0
# Finally, load ModSecurity
LoadModule security2_module /opt/modsecurity/bin/mod_security2.so
With these changes we will run the same script again and compare the results. lab@lab:~$ echo " " >/opt/modsecurity/var/log/debug.log
lab@lab:~$ for i in `seq 1 1000`; do wget -qO /dev/null http://localhost/; done
lab@lab:~$ let sum=0;for duration in
$(grep "Script completed in " /opt/modsecurity/var/log/debug.log|
cut -d " " -f 8); { let sum=$sum+$duration; };
let average=$sum/1000;echo $average
112
As you can see the script execution went from 616 microseconds down to 112 microseconds. While the example script we used here was simplistic and added little overhead to begin with, with the changes described above more complex Lua scripts can be run with greater efficiency.
0 comments:
Post a Comment