LUA Scripts
Tips
Most defense logic and execution order in this project are encapsulated in LUA scripts.
Basic Structure
function should_block()
local req = request
local client_ip = req.client_ip or ""
local site_id = req.site_id or 0
if client_ip == "" then
return 0
end
if is_ip_blacklisted(client_ip, site_id) then
log("Blocked by IP blacklist: " .. client_ip .. " (site_id=" .. tostring(site_id) .. ")")
return 1
end
return 0
end
Tips
As shown above, the script must be a function and must return one of: 0, 1, or -1.
| Return Value | Meaning |
|---|---|
| 0 | Do not block, continue with later scripts |
| 1 | Block the request |
| -1 | Do not block, and skip all later scripts |
Global Objects
To simplify defense customization, several global objects are injected into LUA scripts.
request: request context
This object contains request context with the following fields:
| Field | Default | Description |
|---|---|---|
| method | HTTP method | |
| uri | Request URI | |
| headers | Request headers | |
| body | Request body. Large bodies may be truncated for performance | |
| client_ip | Source IP selection: 1) if trusted_source is configured and request is from a trusted source, IP is selected from X-Real-IP -> X-Forwarded-For (first) -> peer_ip; 2) if trusted_source is not configured, use direct peer IP (which could be upstream nginx) | |
| timestamp | Request timestamp | |
| site_id | Target site ID |
log: logging helper
For debugging, scripts can print logs directly:
log("Blocked by IP blacklist: " .. client_ip .. " (site_id=" .. tostring(site_id) .. ")")
Built-in defense helpers
The script runtime provides several built-in helper methods.
is_verified_crawler: crawler verification
function should_block()
local req = request
local user_agent = req.headers["user-agent"] or req.headers["User-Agent"] or ""
if user_agent == "" then return 1 end
local client_ip = req.client_ip or ""
local exempts = {"MicroMessenger", "DingTalk"}
local value = is_verified_crawler(client_ip, user_agent, nil, 0) -- do not blacklist, block directly
-- log("is_verified_crawler returned: " .. tostring(value))
return value
end
Parameters of is_verified_crawler
| Name | Type | Default | Description |
|---|---|---|---|
| client_ip | string | Request IP | |
| user_agent | string | Request UA | |
| exempts | list of UA strings | Exempt from blacklisting. If fake crawler is detected, only reject request without blacklisting IP | |
| block_duration | number | Blacklist duration in minutes when fake crawler is detected |
is_ip_blacklisted: blacklist check
function should_block()
local req = request
local client_ip = req.client_ip or ""
local site_id = req.site_id or 0
if client_ip == "" then
return 0
end
if is_ip_blacklisted(client_ip, site_id) then
log("Blocked by IP blacklist: " .. client_ip .. " (site_id=" .. tostring(site_id) .. ")")
return 1
end
return 0
end
is_ip_whitelisted: whitelist check
function should_block()
local req = request
local client_ip = req.client_ip or ""
local site_id = req.site_id or 0
if client_ip == "" then
return 0
end
if is_ip_whitelisted(client_ip, site_id) then
log("Allowed by IP whitelist: " .. client_ip .. " (site_id=" .. tostring(site_id) .. ")")
return -1 -- skip all later scripts
end
return 0
end
is_rate_limited: request rate limit check
function should_block()
local req = request
local ip = req.client_ip or "unknown"
local site = req.site_id or 0
-- If CC limited, block immediately
if is_rate_limited(ip, site) then
log("CC rate limited: " .. ip .. " @site " .. tostring(site))
return 1
end
return 0
end
