LUA脚本
提示
本项目主要的防御逻辑和顺序都已经封装到lua脚本中了。
基本结构
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
提示
如上例子所示,脚本必须是一个function,返回值是0、1、-1三个值
| 返回值 | 说明 | |
|---|---|---|
| 0 | 不阻止请求,继续后续脚本 | |
| 1 | 阻止请求 | |
| -1 | 不阻止请求,并跳过所有后续脚本 |
全局对象
为了方便定义防御能力,我们给lua脚本注入了一些全局对象
request 请求上下文
这个是请求的上下文,它包含以下属性
| 属性 | 默认值 | 说明 |
|---|---|---|
| method | 请求的方法 | |
| uri | 请求的uri | |
| headers | 请求的headers | |
| body | 请求的body,注意这里的body如果太大,会被截断保障性能 | |
| client_ip | 请求ip,这个ip地址来源是:1、如果配置了trusted_source,并且请求来自于授信源,那就从X-Real-IP -> X-Forwarded-For(取第一个) -> peer_ip;2、如果没有配置trusted_source,就取请求来源ip(如果有上位nginx,就会取到上位nginx) | |
| timestamp | 请求的时间戳 | |
| site_id | 请求指向的站点id |
log 日志方法
为了方便调试,脚本也可以直接输出日志,调用方法如下
log("Blocked by IP blacklist: " .. client_ip .. " (site_id=" .. tostring(site_id) .. ")")
内置防御方法
脚本还内置了一些常用的防御方法:
is_verified_crawler 爬虫校验
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) -- 不拉黑,直接拦截
-- log("is_verified_crawler returned: " .. tostring(value))
return value
end
is_verified_crawler方法参数
| 参数名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| client_ip | 字符串 | 请求的ip地址 | |
| user_agent | 字符串 | 请求的UA | |
| exempts | UA字符串列表 | 豁免屏蔽,如果识别到冒充爬虫,只拒绝请求,不拉黑ip | |
| block_duration | 数字 | 检测到冒充爬虫的,拉黑分钟数 |
is_ip_blacklisted 黑名单校验
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 白名单校验
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 -- 跳过所有后续脚本
end
return 0
end
is_rate_limited 请求频率
function should_block()
local req = request
local ip = req.client_ip or "unknown"
local site = req.site_id or 0
-- 若被 CC 限制,则立即阻断
if is_rate_limited(ip, site) then
log("CC rate limited: " .. ip .. " @site " .. tostring(site))
return 1
end
return 0
end
