nginx + lua 限制訪問
阿新 • • 發佈:2018-04-23
lua nginx
local redis = require ‘resty.redis‘
local cache = redis.new()
local ok ,err = cache.connect(cache,‘127.0.0.1‘,‘6379‘)
cache:set_timeout(60000)
-- 如果連接失敗,跳轉到label處
if not ok then
goto label
end
-- 白名單
is_white ,err = cache:sismember(‘whitelist‘,ngx.var.remote_addr)
if is_white == 1 then
goto label
end
-- 黑名單
is_black ,err = cache:sismember(‘blacklist‘,ngx.var.remote_addr)
if is_black == 1 then
ngx.exit(ngx.HTTP_FORBIDDEN)
goto label
end
ip_forum_edittopic, err = cache:get(‘ip_forum_edittopic:‘ .. ngx.var.remote_addr)
if ip_forum_edittopic == ngx.null then
res , err = cache:set(‘ip_forum_edittopic:‘ .. ngx.var.remote_addr, 1)
res , err = cache:expire(‘ip_forum_edittopic:‘ .. ngx.var.remote_addr, 43200) -- 12h重置
end
is_forum_ban , err = cache:get(‘ip_forum_edittopic:‘ .. ngx.var.remote_addr)
if tonumber(is_forum_ban) > 80 then
local source = ngx.encode_base64(ngx.var.scheme .. ‘://‘ ..
ngx.var.host .. ‘:‘ .. ngx.var.server_port .. ngx.var.request_uri)
local dest = ‘http://127.0.0.1:5000/‘ .. ‘?continue=‘ .. source
ngx.redirect(dest,302)
goto label
else
res , err = cache:incr(‘ip_forum_edittopic:‘ .. ngx.var.remote_addr)
end
-- ip訪問頻率時間段
ip_time_out = 60
-- ip訪問頻率計數最大值
connect_count = 45
-- 60s內達到45次就ban
-- 封禁ip時間(加入突曲線增長算法)
ip_ban_time, err = cache:get(‘ip_ban_time:‘ .. ngx.var.remote_addr)
if ip_ban_time == ngx.null then
ip_ban_time = 300
res , err = cache:set(‘ip_ban_time:‘ .. ngx.var.remote_addr, ip_ban_time)
res , err = cache:expire(‘ip_ban_time:‘ .. ngx.var.remote_addr, 43200) -- 12h重置
end
-- 查詢ip是否在封禁時間段內,若在則跳轉到驗證碼頁面
is_ban , err = cache:get(‘ban:‘ .. ngx.var.remote_addr)
if tonumber(is_ban) == 1 then
-- source攜帶了之前用戶請求的地址信息,方便驗證成功後返回原用戶請求地址
local source = ngx.encode_base64(ngx.var.scheme .. ‘://‘ ..
ngx.var.host .. ‘:‘ .. ngx.var.server_port .. ngx.var.request_uri)
local dest = ‘http://127.0.0.1:5000/‘ .. ‘?continue=‘ .. source
ngx.redirect(dest,302)
goto label
end
-- ip記錄時間key
start_time , err = cache:get(‘time:‘ .. ngx.var.remote_addr)
-- ip計數key
ip_count , err = cache:get(‘count:‘ .. ngx.var.remote_addr)
-- 如果ip記錄時間的key不存在或者當前時間減去ip記錄時間大於指定時間間隔,則重置時間key和計數key
-- 如果當前時間減去ip記錄時間小於指定時間間隔,則ip計數+1,
-- 並且ip計數大於指定ip訪問頻率,則設置ip的封禁key為1,同時設置封禁key的過期時間為封禁ip時間
if start_time == ngx.null or os.time() - tonumber(start_time) > ip_time_out then
res , err = cache:set(‘time:‘ .. ngx.var.remote_addr , os.time())
res , err = cache:set(‘count:‘ .. ngx.var.remote_addr , 1)
else
ip_count = ip_count + 1
res , err = cache:incr(‘count:‘ .. ngx.var.remote_addr)
-- 統計當日訪問ip集合
res , err = cache:sadd(‘statistic_total_ip:‘ .. os.date(‘%x‘), ngx.var.remote_addr)
if ip_count >= connect_count then
res , err = cache:set(‘ban:‘ .. ngx.var.remote_addr , 1)
res , err = cache:expire(‘ban:‘ .. ngx.var.remote_addr , ip_ban_time)
res , err = cache:incrby(‘ip_ban_time:‘ .. ngx.var.remote_addr, ip_ban_time)
-- 統計當日屏蔽ip總數
res , err = cache:sadd(‘statistic_ban_ip:‘ .. os.date(‘%x‘), ngx.var.remote_addr)
end
end
::label::
local ok , err = cache:close()
nginx + lua 限制訪問