高频访问IP限制 --Openresty(nginx + lua + redis)

[ 2022-04-22 10:25:18 | 作者: admin ]
字号: | |
在openresty下接入Lua脚本就一句话,下面给出nginx.conf示范:

nginx.conf
worker_processes 1;
error_log logs/error.log;
events {
         worker_connections 1024;
}
http {
         server {
                listen 80;
                location / {
                     access_by_lua_file 'lua/access.lua';
                     content_by_lua 'ngx.say("Welcome PENIS!")';
                }
         }
}


access.lua
-- package.path = '/usr/local/openresty/nginx/lua/?.lua;/usr/local/openresty/nginx/lua/lib/?.lua;'
-- package.cpath = '/usr/local/openresty/nginx/lua/?.so;/usr/local//openresty/nginx/lua/lib/?.so;'

-- 连接redis
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('white_list', ngx.var.remote_addr)
if is_white == 1 then
     goto label
end

-- 黑名单
is_black ,err = cache:sismember('black_list', ngx.var.remote_addr)
if is_black == 1 then
     ngx.exit(ngx.HTTP_FORBIDDEN)
     goto label
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()



https://blog.csdn.net/qq_29245097/article/details/77461719?
[最后修改由 admin, 于 2022-04-22 10:28:01]
评论Feed 评论Feed: http://blog.xg98.com/feed.asp?q=comment&id=2839

这篇日志没有评论。

此日志不可发表评论。