ShareThis

12/02/2011 Speeding Up Lua Script Execution in ModSecurity



    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
    
    http://sourceforge.net/apps/mediawiki/mod-security/nfs/project/m/mo/mod-security/thumb/c/cf/Apache_request_cycle-modsecurity.jpg/600px-Apache_request_cycle-modsecurity.jpg 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.
Digg it StumbleUpon del.icio.us
Related Posts Plugin for WordPress, Blogger...

Recent Posts


Popular Posts

Facebook Comment

Trade traffic with me using 2leep.com system