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
}
}