nginx和lua都注重性能,使用lua扩展nginx大大增强了nginx的灵活性。nginx支持lua需要用到ngx_lua模块,在nginx wiki中推荐使用openresty,编译时加上--with-luajit参数就行了,我用的模块不多,更喜欢轻量和高性能的tengine,采用手动编译也不复杂。

一、准备

服务器环境:centos 6.6 64位 ,tengine2.1.0 , openssl和pcre使用yum安装
软件下载:

  1. LuaJIT推荐使用2.1版本,2.0的源码中已经包含了2.1的分支:

    git clone http://luajit.org/git/luajit-2.0.git
    
  2. 安装zlib、openssl和pcre,偷懒使用yum安装:

    yum install zlib zlib-devel openssl openssl-devel pcre pcre-devel
    
  3. 下载tengine和ngx_lua_waf:

    wget http://tengine.taobao.org/download/tengine-2.1.0.tar.gz
    git clone https://github.com/loveshell/ngx_lua_waf
    

二、编译LuaJIT和tengine

2.1 安装 LuaJIT2.1

lua或luaJIT都能支持ngx_lua模块,lua版本最高支持到5.1,出于效率考虑推荐使用luaJIT,我们克隆下来的luaJIT版本是2.0,官方推荐使用2.1开发版,切换到2.1的分支:

cd luajit-2.0 && git checkout v2.1

编译:

make
make install PREFIX=/usr/local/luajit

安装好后LUAJIT_LIB和LUAJIT_INC的路径是:
库文件 LUAJIT_LIB=/usr/local/luajit/lib
头文件 LUAJIT_INC=/usr/local/luajit/include/luajit-2.1
这两个路径编译tengine时要用到。

2.2编译tengine:

 ./configure --prefix=/opt/nginx --with-http_lua_module --with-luajit-lib=/usr/local/luajit/lib/ --with-luajit-inc=/usr/local/luajit/include/luajit-2.1/ --with-ld-opt=-Wl,-rpath,/usr/local/luajit/lib

make && make install

测试:
在nginx.conf中添加一个location:

location /lua { 
     default_type 'text/plain'; 
    content_by_lua 'ngx.say("hello, lua")'; 
}

启动nginx,访问:http://serverIP/lua ,如果出现 hello,lua 就安装成功了。

三、配置ngx_lua_waf

nginx下常见的开源waf有mod_security、naxsi、ngx_lua_waf这三个,mod_security是最老牌的,功能最强规则细定制性又强,但是配置最复杂高并发时性能差。naxsi是原生nginx下的waf,性能不错但是基于白名单,配置也很麻烦。ngx_lua_waf功能和规则虽然没有这两个强大,但赢在性能高和易用性强,基本上零配置,而且常见的攻击类型都能防御,是比较省心的选择。安装好ngx_lua后,把下载好的ngx_lua_waf复制到conf目录下,重命名为waf,在nginx.conf的http段添加:

lua_package_path "/opt/nginx/conf/waf/?.lua";
lua_shared_dict limit 10m;
init_by_lua_file  /opt/nginxconf/waf/init.lua; 
access_by_lua_file /opt/nginx/conf/waf/waf.lua;

修改/opt/nginx/conf/waf/config.lua文件,该文件为waf的配置文件,将RulePath和logdir改为实际的目录:

RulePath = "/opt/nginx/conf/waf/wafconf/"
logdir = "/opt/nginx/logs/waf"   //确保此文件夹nginx有写入权限

其它的安全配置,按照实际需要开启。设置好和启动nginx

测试规则是否生效:

任意文件读取:

curl http://xxxx/test.php?id=../etc/passwd

sql注入:

curl http://xxxx/test.php?id=1 select * from admin

返回禁止页面就说明配置成功了。

如果只是某一个虚拟主机需要开启waf,将nginx.conf中的 access_by_lua_file注释掉,放到需要开启waf的虚拟主机的server段中即可

四、遇到的问题

启动nginx报错:

./nginx: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory

编译时加参数:

--with-ld-opt=-Wl,-rpath,/usr/local/luajit/lib

意思是:为链接器添加额外的参数,将/usr/local/luajit/lib添加到nginx的二进制文件中,防止启动时找不到luaJIT的动态链接库。

参考文章
http://wiki.nginx.org/HttpLuaModule
http://www.cnblogs.com/ghj1976/p/3535818.html
https://github.com/loveshell/ngx_lua_waf