这篇文章上次修改于 2955 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
注:原创,转载请注明来处
最近公司短信验证码获取接口被攻击,查看nginx日志,访问的ip都是同一个,做了一个简单的防刷脚本。
package.path = '/usr/local/luajit/share/lua/5.1/?.lua;'
package.cpath = '/usr/local/luajit/lib/lua/5.1/?.so;'
local function close_memcache(memc)
if not memc then
return
end
--释放连接(连接池实现)
local pool_max_idle_time = 10000 --毫秒
local pool_size = 100 --连接池大小
local ok, err = memc:set_keepalive(pool_max_idle_time, pool_size)
if not ok then
ngx.log(ngx_ERR, "set memcache keepalive error : ", err)
end
end
local memcached = require "resty.memcached"
local cjson = require "cjson"
local uri = ngx.var.uri -- 获取当前请求的uri
local memc, err = memcached:new()
if not memc then
return
end
memc:set_timeout(1000)
local ok, err = memc:connect("10.117.*.*", 12211)
if not ok then
return close_memcache(memc)
end
local clientIP = ngx.req.get_headers()["X-Real-IP"]
if clientIP == nil then
clientIP = ngx.req.get_headers()["x_forwarded_for"]
end
if clientIP == nil then
clientIP = ngx.var.remote_addr
end
--短信验证码限制 一个小时内同一个ip访问超过3000次 此ip屏蔽10分钟
local smsstr = string.lower(uri)
local smsindex = string.find(smsstr, 'util/sms', 0)
if smsindex ~= nil then
local smsincrKey = "smsincr:"..clientIP..":"..ngx.md5(smsstr)..":"..os.date('%Y%m%d%H')
local smslockKey = "smslock:"..clientIP..":"..ngx.md5(smsstr)
local smslock = memc:get(smslockKey)
smslock = tonumber(smslock)
if smslock == 1 then
close_memcache(memc)
ngx.print('{"error":"0","errorMsg":"","total":0,"data":[]}')
ngx.exit(200)
end
local smsres, err = memc:incr(smsincrKey, 1)
if smsres == nil then
smsres , err = memc:set(smsincrKey, 1, 3600)
end
smsres = tonumber(smsres)
if smsres > 3000 then
memc:set( smslockKey, 1, 1200 )
memc:set( smsincrKey, 1 )
end
end
--如果1秒种之内同一个ip访问的同一个地址的次数大于10次 此ip访问此地址时锁定10分钟不给访问
local incrKey = "lock:"..clientIP..":"..ngx.md5(uri)..":"..ngx.time()
local lockKey = "lock:"..clientIP..":"..ngx.md5(uri)
local lock = memc:get(lockKey)
lock = tonumber(lock)
if lock == 1 then
close_memcache(memc)
ngx.exit(ngx.HTTP_FORBIDDEN)
end
local res, err = memc:incr(incrKey, 1)
if res == nil then
res , err = memc:set(incrKey, 1, 1)
end
res = tonumber(res)
if res > 10 then
memc:set( lockKey, 1, 600 )
end
close_memcache(memc)
已有 33 条评论