lua-resty-waf
基于 OpenResty 栈构建的高性能 WAF
$ opm get p0pr0ck5/lua-resty-waf
##名称
lua-resty-waf - 基于 OpenResty 栈构建的高性能 WAF
##目录
-
[nameservers] (#nameservers)
##状态
[!构建状态](https://travis-ci.org/p0pr0ck5/lua-resty-waf) [!Codewake](https://www.codewake.com/p/lua-resty-waf)
lua-resty-waf 目前处于积极开发中。在问题跟踪器中打开的新错误和问题将在一天或两天内得到答复,性能影响和安全相关问题将优先得到修复。当开发资源可用时,将添加更大的功能集和增强功能(有关计划功能的概述,请参见路线图部分)。
lua-resty-waf 与 lua-resty-core
的 master 分支兼容。最近版本的 OpenResty(>= 1.9.7.4)中提供的 lua-resty-core
的捆绑版本与 lua-resty-waf 兼容;与旧版 OpenResty 捆绑包捆绑在一起的版本则不兼容,因此希望利用 resty.core
的用户需要将本地版本替换为 GitHub 项目 中提供的版本,或根据此提交修补模块。
##描述
lua-resty-waf 是使用 OpenResty 栈构建的反向代理 WAF。它使用 Nginx Lua API 来分析 HTTP 请求信息并针对灵活的规则结构进行处理。lua-resty-waf 附带一个模仿 ModSecurity CRS 的规则集,以及在初始开发和测试过程中构建的一些自定义规则,以及一个用于新兴威胁的小型虚拟补丁集。此外,lua-resty-waf 还附带用于自动翻译现有 ModSecurity 规则的工具,允许用户扩展 lua-resty-waf 的实现,而无需学习新的规则语法。
lua-resty-waf 最初由 Robert Paprocki 为其在西方州长大学的硕士论文开发。
##要求
lua-resty-waf 需要几个第三方 resty lua 模块,但这些模块都与 lua-resty-waf 打包在一起,因此无需单独安装。建议在运行 OpenResty 软件包的系统上安装 lua-resty-waf;lua-resty-waf 尚未在使用单独的 Nginx 源代码和 Nginx Lua 模块包构建的平台上进行测试。
为了获得最佳的正则表达式编译性能,建议使用支持 JIT 编译的 PCRE 版本构建 Nginx/OpenResty。如果您的操作系统没有提供此功能,您可以将支持 JIT 的 PCRE 直接构建到 Nginx/OpenResty 构建中。为此,请在 --with-pcre
配置标志中引用 PCRE 源代码的路径。例如
# ./configure --with-pcre=/path/to/pcre/source --with-pcre-jit
您可以从 PCRE 网站 下载 PCRE 源代码。另请参见 这篇博文,了解使用支持 JIT 的 PCRE 库构建 OpenResty 的分步指南。
##性能
lua-resty-waf 的设计理念是效率和可扩展性。它利用 Nginx 的异步处理模型和高效的设计,尽可能快地处理每个事务。负载测试表明,实现所有提供的规则集(旨在模仿 ModSecurity CRS 背后的逻辑)的部署,每秒处理大约 300-500 微秒的请求;这等于 Cloudflare 的 WAF 所宣传的性能。测试是在合理的硬件栈(E3-1230 CPU、32 GB RAM、2 x 840 EVO RAID 0)上运行的,峰值约为每秒 15,000 个请求。有关更多信息,请参见 这篇博文。
lua-resty-waf 的工作负载几乎完全是 CPU 绑定的。Lua VM 中的内存占用(不包括由 lua-shared-dict
支持的持久存储)约为 2MB。
##安装
提供了一个简单的 Makefile
# make && sudo make install
或者,通过 Luarocks 安装
# luarocks install lua-resty-waf
请注意,默认情况下,lua-resty-waf 以模拟模式运行,以防止立即影响应用程序;希望启用规则操作的用户必须显式将操作模式设置为 ACTIVE。
##概要
http {
-- include lua_resty_waf in the appropriate paths
lua_package_path '/usr/local/openresty/lualib/lua_resty_waf/?.lua;;';
lua_package_cpath '/usr/local/openresty/lualib/lua_resty_waf/?.lua;;';
init_by_lua '
-- use resty.core for performance improvement, see the status note above
require "resty.core"
-- require the base module
local lua_resty_waf = require "waf"
-- define options that will be inherited across all scopes
lua_resty_waf.default_option("debug", true)
lua_resty_waf.default_option("mode", "ACTIVE")
-- this may be desirable for low-traffic or testing sites
-- by default, event logs are not written until the buffer is full
-- for testing, flush the log buffer every 5 seconds
lua_resty_waf.default_option("event_log_periodic_flush", 5)
-- perform some preloading and optimization
lua_resty_waf.init()
';
}
server {
location / {
access_by_lua '
local lua_resty_waf = require "waf"
local waf = lua_resty_waf:new()
-- default options can be overridden
waf:set_option("debug", false)
-- run the firewall
waf:exec()
';
header_filter_by_lua '
local lua_resty_waf = require "waf"
-- note that options set in previous handlers (in the same scope)
-- do not need to be set again
local waf = lua_resty_waf:new()
waf:exec()
';
body_filter_by_lua '
local lua_resty_waf = require "waf"
local waf = lua_resty_waf:new()
waf:exec()
';
log_by_lua '
local lua_resty_waf = require "waf"
local waf = lua_resty_waf:new()
-- write out any event log entries to the
-- configured target, if applicable
waf:write_log_events()
';
}
}
##公共函数
###lua_resty_waf.default_option()
为将在所有范围内继承的配置选项定义默认值。当您在许多不同的范围内(例如,许多服务器块、位置等)使用 lua-resty-waf 时,这很有用,并且您不想重复多次调用 set_option
。如果您没有更改选项的值(与定义为默认值的值相同),则不必调用此函数。
http {
init_by_lua '
local lua_resty_waf = require "waf"
lua_resty_waf.default_option("debug", true)
-- this would be a useless operation since it does not change the default
lua_resty_waf.default_option("debug_log_level", ngx.INFO)
';
}
###lua-resty-waf.init()
根据默认分发的规则集以及通过 default_option
添加或忽略的规则集,对规则和规则集执行一些预计算。建议,但不是必需,调用此函数(不这样做会导致轻微的性能损失)。此函数应在 init_by_lua
中的任何 lua-resty-waf 函数调用之后调用,并且永远不应该在此范围之外调用。
示例:
http {
init_by_lua '
local lua_resty_waf = require "waf"
-- set default options...
lua_resty_waf.init()
';
}
##公共方法
###lua-resty-waf:new()
实例化 lua-resty-waf 的新实例。您必须在您希望运行 lua-resty-waf 的每个请求处理程序阶段调用此函数,并使用返回结果来调用进一步的类方法。
示例:
location / {
access_by_lua '
local lua_resty_waf = require "waf"
local waf = lua_resty_waf:new()
';
}
###lua-resty-waf:set_option()
在每个范围内配置一个选项。只有当您要覆盖此范围内的默认值时才应该这样做(例如,在所有地方使用它来定义相同的可配置值是无用的)。
示例:
location / {
access_by_lua '
local lua_resty_waf = require "waf"
local waf = lua_resty_waf:new()
-- enable debug logging only for this scope
waf:set_option("debug", true)
';
}
###lua-resty-waf:reset_option()
将给定选项设置为其记录的默认值,而不管通过 default_option
分配了哪个值。这对于比布尔值或整数值更复杂的选项最有用。
示例:
http {
init_by_lua '
local lua_resty_waf = require "waf"
lua_resty_waf.default_option("allowed_content_types", "text/json")
';
}
[...snip...]
location / {
access_by_lua '
local lua_resty_waf = require "waf"
local waf = lua_resty_waf:new()
-- reset the value to its documented default
waf:reset_option("allowed_content_types")
';
}
###lua-resty-waf:write_log_events()
写入从事务中生成的任何审计日志条目。这应该在 log_by_lua
处理程序中调用。
示例:
location / {
log_by_lua '
local lua_resty_waf = require "waf"
local waf = lua_resty_waf:new()
-- write out any event log entries to the
-- configured target, if applicable
waf:write_log_events()
';
}
##选项
可以使用 default_option
和 set_option
函数配置模块选项。在 init_by_lua
处理程序中使用 default_option
,并且不调用 lua-resty-waf:new()
来设置将在所有范围内继承的默认值。这些值(或未被 default_option
修改的选项)可以在每个范围内通过 set_option
进行进一步调整。此外,范围级别选项可以通过 reset_option
方法重新调整回记录的默认值。这将把给定选项设置为其记录的默认值,覆盖由 default_option
函数设置的默认值。
请注意,在早期阶段处理程序中设置的选项不需要在后面的阶段重新设置,但可以被覆盖(即,您可以在 access
阶段设置 debug
,但在 header_filter
中禁用它。有关可用选项的详细信息,请参见下文。
###add_ruleset
默认值:无
添加要用于处理的附加规则集。这允许用户实现自定义规则集,而不会覆盖包含的规则目录。附加规则集必须位于名为“rules”的文件夹中,该文件夹位于 lua_package_path
中。
示例:
http {
-- the lua module 50000.lua must live at
-- /path/to/extra/rulesets/rules/50000.lua
lua_package_path '/path/to/extra/rulesets/?.lua;;';
}
location / {
access_by_lua '
waf:set_option("add_ruleset", "50000_extra_rules")
';
}
可以通过将值表传递给 set_option
来添加多个规则集。请注意,规则集名称在处理之前会进行排序。规则集以低到高的排序顺序进行处理。
###add_ruleset_string
默认值:无
添加要用于处理的附加规则集。这允许用户实现自定义规则集,而不会覆盖包含的规则目录。规则集以 Lua 字符串的形式内联定义,形式为已翻译的规则集 JSON 结构。
示例:
location / {
access_by_lua '
waf:set_option("add_ruleset_string", "70000_extra_rules", [=[{"access":[{"action":"DENY","id":73,"operator":"REGEX","opts":{},"pattern":"foo","vars":[{"parse":{"values":1},"type":"REQUEST_ARGS"}]}],"body_filter":[],"header_filter":[]}]=])
';
}
请注意,规则集名称在处理之前会进行排序,并且必须以字符串的形式给出。规则集以低到高的排序顺序进行处理。
###allow_unknown_content_types
默认值:false
指示 lua-resty-waf 在发送了不在 allowed_content_types
表中的 Content-Type 标头时继续处理请求。此类请求不会由 lua-resty-waf 处理其请求主体(REQUEST_BODY
集合将为 nil)。通过这种方式,用户无需显式白名单他们可能遇到的所有可能的 Content-Type 标头。
示例:
location / {
access_by_lua '
waf:set_option("allow_unknown_content_types", true)
';
}
###allowed_content_types
默认值:无
定义一个或多个允许的 Content-Type 标头,除了默认的 Content-Type application/x-www-form-urlencoded
和 multipart/form-data
之外。其内容类型与 allowed_content_types
中的某个值匹配的请求将把 REQUEST_BODY
集合设置为包含单个字符串(而不是表);其内容类型与这些值之一或 application/x-www-form-urlencoded
或 multipart/form-data
不匹配的请求将被拒绝。
示例:
location / {
access_by_lua '
-- define a single allowed Content-Type value
waf:set_option("allowed_content_types", "text/xml")
-- defines multiple allowed Content-Type values
waf:set_option("allowed_content_types", { "text/html", "text/json", "application/json" })
';
}
请注意,使用 allowed_content_types
参数的多个 set_option
调用将简单地覆盖现有的选项表,因此如果您要定义多个允许的内容类型,则必须将它们定义为 Lua 表,如上所示。
###debug
默认值:false
禁用/启用调试日志记录。调试日志语句打印到 error_log。请注意,调试日志记录非常昂贵,不应在生产环境中使用。
示例:
location / {
access_by_lua '
waf:set_option("debug", true)
';
}
###debug_log_level
默认值:ngx.INFO
设置用于调试日志记录的 nginx 日志级别常量。
示例:
location / {
access_by_lua '
waf:set_option("debug_log_level", ngx.DEBUG)
';
}
###deny_status
默认值:ngx.HTTP_FORBIDDEN
设置拒绝请求时要使用的状态。
示例:
location / {
access_by_lua '
waf:set_option("deny_status", ngx.HTTP_NOT_FOUND)
';
}
###disable_pcre_optimization
默认值:false
从所有 ngx.re.match
、ngx.re.find
和 ngx.re.sub
调用中删除 oj
标志。这可能在使用旧版 PCRE 库的某些情况下有用,但会导致严重的性能下降,因此强烈不建议使用;相反,用户鼓励使用现代的、支持 JIT 的 PCRE 库构建 OpenResty。
示例:
location / {
access_by_lua '
waf:set_option("disable_pcre_optimization", true)
';
}
###event_log_altered_only
默认值:true
确定是否为未被 lua-resty-waf 修改的事务中的规则匹配写入日志条目。“修改”的定义是 lua-resty-waf 对其操作为 ACCEPT
或 DENY
的规则采取行动。当此选项未设置时,即使事务未被修改,lua-resty-waf 也会记录规则匹配。默认情况下,lua-resty-waf 仅在事务被修改时才会为匹配项写入日志条目。
示例:
location / {
access_by_lua '
waf:set_option("event_log_altered_only", false)
';
}
请注意,mode
不会影响判断交易是否被修改。也就是说,如果匹配到具有 DENY
操作的规则,但 lua-resty-waf 在 SIMULATE
模式下运行,该交易仍将被视为已修改,并且将记录规则匹配。
###event_log_buffer_size
默认: 4096
定义用于保存事件日志的缓冲区的阈值大小(以字节为单位)。当达到此阈值时,将刷新缓冲区。
示例:
location / {
access_by_lua '
-- 8 KB event log message buffer
waf:set_option("event_log_buffer_size", 8192)
';
}
###event_log_level
默认值:ngx.INFO
设置用于事件日志记录的 nginx 日志级别常量。
示例:
location / {
access_by_lua '
waf:set_option("event_log_level", ngx.WARN)
';
}
###event_log_ngx_vars
默认:空
定义从 ngx.var
中将哪些额外的变量放入日志事件中。这是一种将警报与额外上下文扩展的通用方法。变量名称将是日志条目中 ngx
键下的条目的键。如果变量不存在为 nginx 变量,则不会将任何项目添加到事件中。
示例:
location / {
access_by_lua '
waf:set_option("event_log_ngx_vars", "host")
waf:set_option("event_log_ngx_vars", "request_id")
';
}
生成的事件具有以下额外项目
{
"ngx": {
"host": "example.com",
"request_id": "373bcce584e3c18a"
}
}
###event_log_periodic_flush
默认值:无
定义事件日志缓冲区定期刷新的时间间隔(以秒为单位)。如果没有配置任何值,缓冲区将不会定期刷新,而只会当达到 event_log_buffer_size
阈值时才刷新。为可能在很长一段时间内未收到任何事件日志数据的流量非常低的站点配置此选项,以防止过时数据停留在缓冲区中。
示例:
location / {
access_by_lua '
-- flush the event log buffer every 30 seconds
waf:set_option("event_log_periodic_flush", 30)
';
}
###event_log_request_arguments
默认值:false
当设置为 true 时,日志条目包含 uri_args
键下的请求参数。
示例:
location / {
access_by_lua '
waf:set_option("event_log_request_arguments", true)
';
}
###event_log_request_body
默认值:false
当设置为 true 时,日志条目包含 request_body
键下的请求正文。
示例:
location / {
access_by_lua '
waf:set_option("event_log_request_arguments", true)
';
}
###event_log_request_headers
默认值:false
HTTP 请求的标头将被复制到日志事件中,位于 request_headers
键下。
示例:
location / {
access_by_lua '
waf:set_option("event_log_request_headers", true)
';
}
生成的事件具有以下额外项目
{
"request_headers": {
"accept": "*/*",
"user-agent": "curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3"
}
}
###event_log_ssl
默认值:false
通过 TCP/UDP 日志记录时启用 SSL 连接。
示例:
location / {
access_by_lua '
waf:set_option("event_log_ssl", true)
';
}
###event_log_ssl_sni_host
默认值:无
为 lua-resty-logger-socket
连接设置 SNI 主机。
示例:
location / {
access_by_lua '
waf:set_option("event_log_ssl_sni_host", "loghost.example.com")
';
}
###event_log_ssl_verify
默认值:false
通过 TCP/UDP 日志记录时启用 SSL 连接的证书验证。
示例:
location / {
access_by_lua '
waf:set_option("event_log_ssl_verify", true)
';
}
###event_log_socket_proto
默认:udp
定义通过远程套接字发送事件日志时要使用的 IP 协议(TCP 或 UDP)。无论协议如何,都将使用相同的缓冲和循环刷新逻辑。
示例:
location / {
access_by_lua '
-- send logs via TCP
waf:set_option("event_log_socket_proto", "tcp")
';
}
###event_log_target
默认:error
定义事件日志的目标。lua-resty-waf 目前支持将日志记录到错误日志、本地文件系统上的单独文件或远程 TCP 或 UDP 服务器。在后两种情况下,事件日志将被缓冲,并在达到定义的阈值时刷新(有关事件日志记录选项的更多选项,请参见下面的内容)。
示例:
location / {
access_by_lua '
-- send event logs to the server's error_log location (default)
waf:set_option("event_log_target", "error")
-- send event logs to a local file on disk
waf:set_option("event_log_target", "file")
-- send event logs to a remote server
waf:set_option("event_log_target", "socket")
';
}
请注意,由于使用的日志记录库中的限制,只能定义一个目标套接字(和单独的文件目标)。也就是说,您可以选择在不同位置同时使用套接字和文件日志记录,但您只能配置一个具有特定主机/端口组合的 socket
目标;如果您配置第二个主机/端口组合,数据将无法正确记录。类似地,如果您使用 file
日志记录目标,您只能定义一个文件路径;写入第二个路径位置的数据将丢失。
###event_log_target_host
默认值:无
为目标远程服务器的事件日志定义目标服务器。
示例:
location / {
access_by_lua '
waf:set_option("event_log_target_host", "10.10.10.10")
';
}
###event_log_target_path
默认值:无
为目标本地文件系统位置的事件日志定义目标路径。
示例:
location / {
access_by_lua '
waf:set_option("event_log_target_path", "/var/log/lua-resty-waf/event.log")
';
}
此路径必须位于 nginx 用户可写入的位置。请注意,从本质上讲,磁盘上的日志记录会导致高并发环境中的性能明显下降。
###event_log_target_port
默认值:无
为目标远程服务器的事件日志定义目标端口。
示例:
location / {
access_by_lua '
waf:set_option("event_log_target_port", 9001)
';
}
###event_log_verbosity
默认: 1
设置用于写入事件日志通知的详细程度。详细程度越高,为每个通知生成的 JSON 块中包含的信息就越多。
示例:
location / {
access_by_lua '
-- default verbosity. the client IP, request URI, rule match data, and rule ID will be logged
waf:set_option("event_log_verbosity", 1)
-- the rule description will be written in addition to existing data
waf:set_option("event_log_verbosity", 2)
-- the rule description, options and action will be written in addition to existing data
waf:set_option("event_log_verbosity", 3)
-- the entire rule definition, including the match pattern, will be written in addition to existing data
-- note that for some rule definitions, such as the XSS and SQLi rulesets, this pattern can be large
waf:set_option("event_log_verbosity", 4)
';
}
###hook_action
默认值:无
覆盖匹配规则时执行的操作的功能。有关更多详细信息,请参见示例。
示例:
location / {
access_by_lua '
local deny_override = function(waf, ctx)
ngx.log(ngx.INFO, "Overriding DENY action")
ngx.status = 404
end
-- override the DENY action with the function defined above
waf:set_option("hook_action", "DENY", deny_override)
';
}
###ignore_rule
默认值:无
指示模块忽略指定的规则 ID。请注意,忽略链中的规则会导致整个链被忽略,处理将继续到链后的下一条规则。
示例:
location / {
access_by_lua '
waf:set_option("ignore_rule", 40294)
';
}
可以通过将规则 ID 表传递给 set_option
来忽略多条规则。
###ignore_ruleset
默认值:无
指示模块忽略整个规则集。当某些规则集(例如 SQLi 或 XSS CRS 规则集)太容易产生误报或不适用于您的应用程序时,这可能很有用。
示例:
location / {
access_by_lua '
waf:set_option("ignore_ruleset", "41000_sqli")
';
}
###mode
默认:SIMULATE
设置模块的操作模式。选项为 ACTIVE、INACTIVE 和 SIMULATE。在 ACTIVE 模式下,记录规则匹配并运行操作。在 SIMULATE 模式下,lua-resty-waf 将循环遍历每个启用的规则并记录规则匹配,但不会完成给定运行中指定的动作。INACTIVE 模式会阻止模块运行。
默认情况下,如果未明确设置模式,将选择 SIMULATE;这要求新用户通过将模式设置为 ACTIVE 来主动实现阻止。
示例:
location / {
access_by_lua '
waf:set_option("mode", "ACTIVE")
';
}
###nameservers
默认值:无
设置用于 RBL 查找的 DNS 解析器。目前仅支持 UDP/53 流量。此选项必须定义为数字地址,而不是主机名。如果未定义此选项,所有 RBL 查找规则将返回 false。
示例:
location / {
access_by_lua '
waf:set_option("nameservers", "10.10.10.10")
';
}
###process_multipart_body
默认 true
启用使用 lua-resty-upload
模块处理 multipart/form-data 请求正文(如果存在)。将来,lua-resty-waf 可能会使用此处理来对上传正文执行更严格的检查;目前,此模块仅对请求正文执行最小的健全性检查,如果请求正文无效,将不会记录事件。如果您不需要此检查,或者上游模块中的错误导致 HTTP 上传出现问题,请禁用此选项。
示例:
location / {
access_by_lua '
-- disable processing of multipart/form-data requests
-- note that the request body will still be sent to the upstream
waf:set_option("process_multipart_body", false)
';
}
###req_tid_header
默认值:false
在上游请求中设置 HTTP 标头 X-Lua-Resty-WAF-ID
,其值为事务 ID。此 ID 将与调试日志中存在的事务 ID 相对应(如果设置)。这对于请求跟踪或调试目的可能很有用。
示例:
location / {
access_by_lua '
waf:set_option("req_tid_header", true)
';
}
###res_body_max_size
默认:1048576(1 MB)
定义响应正文将不会被处理的内容长度阈值。响应正文的大小由 Content-Length 响应标头确定。如果响应中不存在此标头,则响应正文将永远不会被处理。
示例:
location / {
access_by_lua '
-- increase the max response size to 2 MB
waf:set_option("res_body_max_size", 1024 * 1024 * 2)
';
}
请注意,从本质上讲,需要缓冲整个响应正文才能正确使用响应作为集合,因此不建议在没有充分理由的情况下(以及充足的服务器资源)大幅增加此数字。
###res_body_mime_types
默认:"text/plain","text/html"
定义 lua-resty-waf 将使用其处理响应正文的 MIME 类型。此值由 Content-Type 标头确定。如果此标头不存在,或者响应类型不在此列表中,则响应正文将不会被处理。设置此选项将向现有的 text/plain
和 text/html
默认值添加给定的 MIME 类型。
示例:
location / {
access_by_lua '
-- mime types that will be processed are now text/plain, text/html, and text/json
waf:set_option("res_body_mime_types", "text/json")
';
}
可以通过将类型表传递给 set_option
来添加多个 MIME 类型。
###res_tid_header
默认值:false
在下游响应中设置 HTTP 标头 X-Lua-Resty-WAF-ID
,其值为事务 ID。此 ID 将与调试日志中存在的事务 ID 相对应(如果设置)。这对于请求跟踪或调试目的可能很有用。
示例:
location / {
access_by_lua '
waf:set_option("res_tid_header", true)
';
}
###score_threshold
默认: 5
设置异常评分的阈值。当达到阈值时,lua-resty-waf 将拒绝请求。
示例:
location / {
access_by_lua '
waf:set_option("score_threshold", 10)
';
}
###storage_backend
默认:dict
定义一个用于持久变量存储的引擎。当前可用的选项是 dict(ngx_lua 共享内存区域)、memcached 和 redis。
示例:
location / {
acccess_by_lua '
waf:set_option("storage_backend", "memcached")
';
}
###storage_keepalive
默认值:true
启用或禁用对远程持久存储主机的连接的 TCP 保持活动状态。
示例:
location / {
acccess_by_lua '
waf:set_option("storage_keepalive", false)
';
}
###storage_keepalive_timeout
默认: 10000
配置(以毫秒为单位)远程持久存储主机的 cosocket 保持活动状态池的超时时间。
示例:
location / {
acccess_by_lua '
waf:set_option("storage_keepalive_timeout", 30000)
';
}
###storage_keepalive_pool_size
默认: 100
配置远程持久存储主机的 cosocket 保持活动状态池的池大小。
示例:
location / {
acccess_by_lua '
waf:set_option("storage_keepalive_pool_size", 50)
';
}
###storage_memcached_host
默认: 127.0.0.1
定义在使用 memcached 作为持久变量存储引擎时要使用的主机。
示例:
location / {
acccess_by_lua '
waf:set_option("storage_host", "10.10.10.10")
';
}
###storage_memcached_port
默认: 11211
定义在使用 memcached 作为持久变量存储引擎时要使用的端口。
示例:
location / {
acccess_by_lua '
waf:set_option("storage_port", 11221)
';
}
###storage_redis_host
默认: 127.0.0.1
定义在使用 redis 作为持久变量存储引擎时要使用的主机。
示例:
location / {
acccess_by_lua '
waf:set_option("storage_host", "10.10.10.10")
';
}
###storage_redis_port
默认: 6379
定义在使用 redis 作为持久变量存储引擎时要使用的端口。
示例:
location / {
acccess_by_lua '
waf:set_option("storage_port", 6397)
';
}
###storage_zone
默认值:无
定义将用于保存持久存储数据的 lua_shared_dict
。此区域必须在配置的 http{}
块中定义。
示例:_
http {
-- define a 64M shared memory zone to hold persistent storage data
lua_shared_dict persistent_storage 64m;
}
location / {
access_by_lua '
waf:set_option("storage_zone", "persistent_storage")
';
}
可以定义和使用多个共享区域,但每个配置位置只能定义一个区域。如果区域已满并且共享字典接口无法添加更多键,则以下内容将被记录到错误日志中
错误将键添加到持久存储中,请增加 lua_shared_dict 的大小
##阶段处理
lua-resty-waf 旨在在请求生命周期的多个阶段运行。可以在以下阶段处理规则
access:在此阶段可以使用请求信息,例如 URI、请求标头、URI 参数和请求正文。
header_filter:在此阶段可以使用响应标头和 HTTP 状态。
body_filter:在此阶段可以使用响应正文。
这些阶段对应于它们各自的 Nginx lua 处理程序(分别为 access_by_lua
、header_filter_by_lua
和 body_filter_by_lua
)。请注意,在不在此列表中的 lua 阶段处理程序中运行 lua-resty-waf 会导致行为出现问题。在较晚阶段可以使用在较早阶段提供的所有数据。也就是说,在 access
阶段提供的数据也将在 header_filter
和 body_filter
阶段提供,但反之则不行。
此外,需要在 log_by_lua
处理程序中调用 write_log_events
。lua-resty-waf 并非旨在在此阶段处理规则;在请求后期记录规则允许将所有规则合并到每个请求的单个条目中。有关示例语法,请参见上面的概要。
##包含的规则集
lua-resty-waf 与许多规则集一起分发,这些规则集旨在模拟 ModSecurity CRS 的功能。为了参考,这些规则集列在这里
11000_whitelist:本地策略白名单
20000_http_violation:HTTP 协议违规
21000_http_anomaly:HTTP 协议异常
35000_user_agent:恶意/可疑用户代理
40000_generic_attack:通用攻击
41000_sqli:SQLi
42000_xss:XSS
90000_custom:自定义规则/虚拟补丁
99000_scoring:异常评分处理
##规则定义
lua-resty-waf 从存储在磁盘上的 JSON 块中解析规则定义。规则根据目的和严重程度进行分组,定义为规则集。包含的规则集旨在模拟 ModSecurity CRS 的某些功能,特别是 base_rules
定义。此外,包含的 modsec2lua-resty-waf.pl
脚本可用于将其他或自定义规则集转换为 lua-resty-waf 兼容的 JSON 块。
请注意,转换脚本在不支持的操作、集合和运算符方面存在一些限制。请参见 此维基页面,了解已知不兼容性的最新列表。
##注释
###社区
有一个 Freenode IRC 频道 #lua-resty-waf
。Travis CI 会在此处发送通知;请随时在此频道中提出问题/留下评论。
此外,CodeWake 提供问答
[!Codewake](https://www.codewake.com/p/lua-resty-waf)
###拉取请求
请将所有拉取请求针对开发分支,或针对功能分支(如果 PR 是重大更改)。对 master 的提交应仅以文档更新或对模块本身没有影响的其他更改(并且可以干净地合并到 development 中)的形式出现。
##路线图
扩展的虚拟补丁规则集:增加对新兴威胁的覆盖范围。
扩展的集成/验收测试:增加对常见威胁和使用场景的覆盖范围。
扩展的 ModSecurity 语法翻译:支持更多运算符、变量和操作。
常用应用程序配置文件:针对常见 CMS/应用程序的调整规则集。
支持多个套接字/文件记录器目标:可能需要分叉 lua-resty-logger-socket 项目。
## 限制
lua-resty-waf 正在不断开发和改进,因此其功能和性能可能有限。目前已知的限制可以在此仓库的 GitHub 问题跟踪器中找到。
## 许可证
本程序是免费软件:您可以在自由软件基金会发布的 GNU 通用公共许可证的条款下重新发布和/或修改它,无论是许可证的版本 3 还是(根据您的选择)任何更高版本。
本程序按“原样”分发,不提供任何形式的保证;甚至不包括适销性或适合特定用途的默示保证。有关更多详细信息,请参阅 GNU 通用公共许可证。
您应该已经收到一份 GNU 通用公共许可证副本,与本程序一起。如果没有,请参见 <https://gnu.ac.cn/licenses/>
## 错误
请通过在 GitHub 问题跟踪器中创建工单来报告错误。
## 另请参阅
OpenResty 项目:<https://openresty.org.cn/>
我个人博客,用于更新和记录 lua-resty-waf 开发:<http://www.cryptobells.com/tag/lua-resty-waf/>
作者
Robert Paprocki (p0pr0ck5)
许可
gpl3
版本
-
p0pr0ck5/lua-resty-waf 0.8.2基于 OpenResty 堆栈构建的高性能 WAF 2016-09-30 01:13:39
-
2016-09-30 00:54:30