使用OpenResty实现简易CC防护
January 2, 2024 默认分类
环境
- CentOS 7
- OpenResty 1.19.9.1
- lua-resty-ipmatcher
- lua-var-nginx-module
功能
- 支持IP白名单
- 支持IP黑名单
- 计数key为:ip + “.” + md5(host + request_uri + useragent),可自定义
- 60秒内请求超过60次就封禁3600秒
配置
对应nginx配置
lua_shared_dict cc_counter 100m;
server {
listen 80;
server_name demo.test.com;
location / {
access_by_lua_file lua/anticc.lua;
}
}
anticc.lua
local require = require
local ngx = ngx
local ipmatcher = require("resty.ipmatcher")
local ngxvar = require("resty.ngxvar")
local ngx_md5 = ngx.md5
-- config
local CCcount = 60
local CCseconds = 60
local blockseconds = 3600
local allowips = ipmatcher.new({
"127.0.0.1",
})
local denyips = ipmatcher.new({
"192.168.0.0/24",
})
local cc_counter = ngx.shared.cc_counter
local req = ngxvar.request()
local IP = ngxvar.fetch("remote_addr")
local request_uri = ngx.var.request_uri
local url = ngxvar.fetch("host") .. request_uri
local ua = ngx.var.http_user_agent or "unknown"
local function anticc_check()
local count_Key = IP .. "." .. ngx_md5(url .. ua)
local countReq = cc_counter:get(count_Key)
if countReq then
if tonumber(countReq) >= CCcount then
local block_Key = "block." .. count_Key
local blockReq = cc_counter:get(block_Key)
if blockReq then
ngx.log(ngx.ERR, "cc_blocked: ", IP)
ngx.exit(444)
else
cc_counter:set(block_Key, 1, blockseconds)
cc_counter:set(count_Key, CCcount, blockseconds)
ngx.log(ngx.ERR, "cc_blocked: ", IP)
ngx.exit(444)
end
else
cc_counter:incr(count_Key, 1)
return
end
else
cc_counter:set(count_Key, 0, CCseconds)
cc_counter:incr(count_Key, 1)
return
end
end
if allowips:match(IP) then
return
elseif denyips:match(IP) then
ngx.log(ngx.ERR, "denyip: ", IP)
return ngx.exit(444)
else
anticc_check()
end