核心是借助ngx_http_lua_module在access阶段注入Lua逻辑实现请求实时检测与拦截,需完成编译集成(推荐OpenResty)、配置lua_package_path与lua_shared_dict、编写waf.lua规则、挂载access_by_lua_file四步协同。

在 Nginx 中用 Lua 实现安全防火墙,核心是借助 ngx_http_lua_module(即 Lua 模块)在请求处理生命周期的关键阶段(如 access 阶段)注入自定义逻辑,对 HTTP 请求实时检测与拦截。这不是装个插件就开箱即用,而是需要编译支持、路径配置、规则编写和精准挂载四步协同。
编译或选用支持 Lua 的 Nginx 环境
原生 Nginx 不含 Lua 支持,必须显式集成:
- 推荐直接使用 OpenResty——它已预编译整合了 Nginx、LuaJIT 和常用 Lua 模块(如 lua-resty-core、lua-resty-limit-traffic),省去手动编译风险;
- 若坚持用原生 Nginx,则需下载
lua-nginx-module、ngx_devel_kit和Luajit,在 configure 时通过--add-module=参数引入,再编译安装; - 验证是否生效:运行
nginx -V 2>&1 | grep -o with-http_lua_module,有输出即表示模块已加载。
配置基础 Lua 运行环境
在 nginx.conf 的 http 块中添加以下关键指令:
-
lua_package_path "/etc/nginx/waf/?.lua;;";:指定 Lua 脚本及依赖模块的查找路径,注意末尾两个分号; -
lua_shared_dict limit 10m;:声明共享内存字典,用于跨 worker 进程存储限流状态或黑名单 IP(如 CC 防御); -
init_by_lua_file /etc/nginx/waf/init.lua;:在 master 进程初始化时加载全局变量或预编译正则,提升性能; -
access_by_lua_file /etc/nginx/waf/waf.lua;:在 access 阶段执行主 WAF 逻辑,此处做规则匹配与拦截决策。
编写可扩展的 WAF 规则逻辑
WAF 的有效性取决于规则质量与执行位置。典型做法是分层过滤:
-
IP 层控制:读取
ngx.var.remote_addr,比对预设黑名单(文件或 Redis),命中即ngx.exit(403); -
URL/参数特征检测:对
ngx.var.request_uri或ngx.var.args使用string.find()或ngx.re.match()匹配 SQL 注入(如"union\s+select")、XSS(如"<script>)等模式;</script> -
CC 防御:用
resty.limit.conn或resty.limit.req基于 IP + URI 维度限流,超限返回503; -
白名单豁免:对管理后台、静态资源路径(如
/static/、/healthz)提前return,跳过全部检查。
启用日志与调试机制
防御不能黑盒运行:
- 在 Lua 脚本中用
ngx.log(ngx.WARN, "Blocked IP:", ip, " for SQLi")记录拦截详情,配合error_log /var/log/nginx/waf.log warn;单独归集; - 开启
lua_code_cache off;(仅开发环境)便于热更新脚本,生产务必关闭以保性能; - 用
curl -I http://your.site/test.php?id=1%20UNION%20SELECT手动验证规则是否触发,观察响应码与日志输出。
不复杂但容易忽略:所有 Lua 脚本中的正则表达式需转义反斜杠,字符串匹配要区分大小写,且 access_by_lua* 阶段无法读取请求体(body),如需检查 POST 内容,必须加 lua_need_request_body on; 并改用 body_filter_by_lua* 或 rewrite_by_lua* 配合 ngx.req.read_body()。


















