WAF 规则

Plus 提供的 WAF 功能也是基于 Edgelang 实现的,所以用户可以通过 Edgelang 编写高效的 WAF 规则集。

我们的 WAF 模块与其他 WAF 模块在使用相同规则集的情况下的性能对比图。

这里我们提供一个拦截 /root.exe 恶意请求的例子。

创建 WAF 模块

WAF 模块 与普通 Edgelang 模块的区别就是 WAF 模块需要使用 waf-mark-risk 标记恶意请求。我们创建一个名为 reject-root 的 WAF 模块,源码如下:

uri eq "/root.exe" =>
    waf-mark-risk(msg: "reject root.exe");

一个 WAF 模块中也可以包含多条规则,例如:

uri eq "/root.exe" =>
    waf-mark-risk(msg: "reject root.exe");

uri contains "/other.exe" =>
    waf-mark-risk(msg: "reject other.exe");

导出 WAF 模块

点击保存并编译,然后可以从下面的编译历史中下载编译后的 zip 压缩包。

解压后将其中的 .ljbc 文件复制到 nginx.conf 中指定的 lua_package_path 目录下。

此外,在列表页面可以通过多选 WAF 模块的方式一次性导出多个 WAF 模块。

使用 WAF 模块

需要使用 orwaf:add_rule_set 添加规则集,然后在服务入口前使用 orwaf:run 运行指定的规则集。 如果请求命中了 WAF 规则集,orwaf:run 会返回命中信息。

  • orwaf:add_rule_set(rule_set_name, rule_set_module_name)

    • rule_set_name: 给规则集定义一个名称,在后面将通过名称来选择要执行的规则集,可以和 WAF 模块名不同。
    • rule_set_module_name: WAF 模块名。
  • orwaf:run(rule_set_names)

    • rule_set_names: 需要运行的规则集列表

以下是一个完整的 nginx.conf 示例。

worker_processes  auto;

events {
    worker_connections  1024;
}

http {
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    lua_shared_dict dymetric_version 1m;
    lua_shared_dymetrics dymetrics 10m;

    init_worker_by_lua_block {
        local orwaf = require "orwaf".new()
        local res, err = orwaf:add_rule_set("reject-root")
        if not res then
            ngx.say("err: ", err)
            return
        end
    }

    server {
        listen       127.0.0.1:80;
        listen       [::1]:80;
        server_name  localhost;

        location / {
            content_by_lua_block {
                local matches, err = orwaf:run({"reject-root"})
                if matches then
                    ngx.log(ngx.ERR, "ok: matches = ", require("cjson.safe").encode(matches))
                    ngx.exit(403)
                end
            }
        }
    }
}

内置规则集

除了可以通过 WAF 模块定义的规则集,我们也内置了 OWASP 的规则集。

  • scanner_detection
  • protocol_enforcement
  • protocol_attack
  • attack_lfi
  • attack_rfi
  • attack_rce
  • attack_php
  • attack_nodejs
  • attack_xss
  • attack_sqli
  • attack_session_fixation
  • attack_java

调用方法和自定义规则集一样。

location / {
    content_by_lua_block {
        local matches, err = orwaf:run({"scanner_detection", "protocol_enforcement", "protocol_attack"})
        if matches then
            ngx.log(ngx.ERR, "ok: matches = ", require("cjson.safe").encode(matches))
            ngx.exit(403)
        end
    }
}