Ubuntu 22.04.4 LTS openresty(Nginx) 通过Lua+Redis 实现动态封禁IP

1 系统环境

test@iZbp1g7fmjea77vsqc5hmmZ:~$ cat  /etc/os-release 
PRETTY_NAME="Ubuntu 22.04.4 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.4 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
#
test@iZbp1g7fmjea77vsqc5hmmZ:~$ /usr/local/openresty/nginx/sbin/nginx  -v
nginx version: openresty/1.25.3.1
#
test@iZbp1g7fmjea77vsqc5hmmZ:~$ redis-cli  -v
redis-cli 7.3.240

2 修改nginx配置

#更加实际情况修改相关配置文件
    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
            access_by_lua_file "/usr/local/openresty/nginx/lua/access_limit.lua";#封禁lua文件
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

3 lua配置文件

sudo vim  /usr/local/openresty/nginx/lua/access_limit.lua
package.path = '/usr/local/openresty/lualib/resty/?.lua;'
function get_client()
    local redis = require "redis"
    client = redis:new()
    client:set_timeout(300000) -- 1 second
    client:set_keepalive(600000, 200)
    local ip = '172.16.195.13'
    local port = 6379
    local redis_db = 11
    local ok, err = client:connect(ip,port)
    if not ok then
        return nil, "failed to connect."
    end
    local ok1,err = client:auth("password")
    if not ok1 then
        return nil, "failed to authenticate."
    end
    client:select(redis_db)
    return client, nil
end

function auth(client, sid)
    key = ":1:"..sid
    local res, err = client:get(key)
    return res, nil
end
local function getIp()
    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
    return clientIP
end
local clientip = getIp()
local incrKey = "ipcount:"..clientip
local blockKey = "iplimit:"..clientip
client, err = get_client()
if err then
    ngx.log(ngx.ERR, "connect redis error:", err)
    ngx.status = 500
    --ngx.say("{\"detail\":\"server error\"}")
    ngx.say("{\"detail\":\"redis sid no !\"}")
    return
end
local is_block,err = client:get(blockKey)
if tonumber(is_block) == 1 then
    ngx.exit(403)
    --ngx.exit(ngx.HTTP_FORBIDDEN)
    client:close()
end
local ip_count, err = client:incr(incrKey)
if  tonumber(ip_count) == 1 then
    client:expire(incrKey,1)
end
if  tonumber(ip_count) > 9 then
    client:set(blockKey,1)
    client:expire(blockKey,7200) -- 封锁IP 2小时
end
client:close()

4 测试,正常访问不超过9次/秒

#如果每秒访问超过9次,如下

#查看redis

5 Redis incr 命令

#存储在指定key中的数值进行自增操作。 当执行INCR命令时,如果key不存在,Redis会创建一个新的key,并将其初始值设置为0,再进行自增操作。如果key的值可以被解释为一个整数,Redis会将其自增1,并返回自增后的值.
127.0.0.1:6379[11]> incr  hihi
相关推荐
微光守望者14 分钟前
Redis常见命令
数据库·redis·缓存
凌波漫步&16 分钟前
通过Redisson构建延时队列并实现注解式消费
redis·电商平台·redisson订单自动取消
bohu8311 小时前
亚博microros小车-原生ubuntu支持系列:16 机器人状态估计
ubuntu·机器人·imu·localization·microros·imu_tools
@_@哆啦A梦14 小时前
Redis 基础命令
java·数据库·redis
千夜啊14 小时前
Nginx 运维开发高频面试题详解
运维·nginx·运维开发
gentle coder16 小时前
Redis_Redission的入门案例、多主案例搭建、分布式锁进行加锁、解锁底层源码解析
java·redis·分布式
萝卜青今天也要开心16 小时前
读书笔记-《Redis设计与实现》(一)数据结构与对象(下)
java·数据结构·redis·学习
java1234_小锋18 小时前
说说Redis的内存淘汰策略?
数据库·redis·缓存
hunter20620619 小时前
如何监控ubuntu系统某个程序的运行状态,如果程序出现异常,对其自动重启。
linux·chrome·ubuntu
2的n次方_1 天前
【Redis】set 和 zset 类型的介绍和常用命令
数据库·redis·缓存