nginx嵌入lua设置IP黑名单
准备工作
- 结合redis缓存实现IP黑名单
- docker 安装 redis 服务
- 使用redis集合数据类型存储IP
安装redis
# 命令来查看可用版本 docker search redis # 拉取官方的最新版本的镜像 docker pull redis:latest # 查看是否已安装了 redis docker images #运行redis容器 #–-requirepass 设置密码 #–-appendonly 开启redis 持久化 docker run -itd --name myredis -p 6379:6379 redis --requirepass "123456" --appendonly yes #查看容器的运行 docker ps #进入容器 docker exec -it myredis sh #连接redis redis-cli auth 123456 #添加IP黑名单 SADD forbidden "192.168.56.1" #移除IP黑名单 SREM forbidden "192.168.56.1"
nginx.conf文件
worker_processes 1; error_log logs/error.log; events { worker_connections 1024; } http { # 设置纯 Lua 扩展库的搜寻路径(';;' 是默认路径) lua_package_path "/data/www/code/nginx+lua/config/lua_p/?.lua;;"; # 设置 C 编写的 Lua 扩展模块的搜寻路径(也可以用 ';;') lua_package_cpath "/data/www/code/nginx+lua/config/lua_p_c/?.so;;"; # 缓存大小5m lua_shared_dict forbidden 5m; server { listen 8080; location /forbidden { #lua_code_cache off; # 关闭lua缓存 修改content_by_lua_file引入文件不用重启nginx就会生效 access_by_lua_file ./config/lua/forbidden.lua; # 引入lua脚本 default_type 'text/html'; content_by_lua 'ngx.say("hello world")'; } } }
forbidden.lua文件
local redis = require("resty.redis"); local ngx_log = ngx.log; local ngx_ERR = ngx.ERR; local ngx_INFO = ngx.INFO; local ngx_exit = ngx.exit; local ngx_var = ngx.var; -- 黑名单缓存60秒 local cache_idle = 60; local forbidden = ngx.shared.forbidden; local function close_redis(red) if not red then return end -- 释放连接(连接池实现) local pool_max_idle_time = 10000; -- 毫秒 local pool_size = 100; -- 连接池大小 local ok, err = red:set_keepalive(pool_max_idle_time, pool_size); if not ok then ngx_log(ngx_ERR, "set redis keepalive error : ", err); end end -- 从redis获取ip黑名单列表 local function get_forbidden() local red = redis:new(); red:set_timeout(1000); local ip = "192.168.56.2"; local port = 6379; local password = "123456"; local ok, err = red:connect(ip, port); -- ngx.say(ok); -- ngx.say('<br>'); if not ok then ngx_log(ngx_ERR, "connect to redis error : ", err); close_redis(red); return end local res, err = red:auth(password) if not res then ngx_log(ngx_ERR, "failed to authenticate: ", err) close_redis(red) return end local resp, err = red:smembers("forbidden") if not resp then ngx_log(ngx_ERR, "get redis connect error : ", err) close_redis(red) return end -- 得到的数据为空处理 if resp == ngx.null then resp = nil end close_redis(red) return resp end -- 刷新黑名单 local function reflush_forbidden() local current_time = ngx.now(); -- ngx.say(current_time); -- ngx.say('<br>'); local last_update_time = forbidden:get("last_update_time"); -- ngx.say(last_update_time); -- ngx.say('<br>'); if last_update_time == nil or last_update_time < (current_time - cache_idle) then local new_forbidden = get_forbidden(); if not new_forbidden then return end forbidden:flush_all(); for i, forbidden_ip in ipairs(new_forbidden) do forbidden:set(forbidden_ip, true); end forbidden:set("last_update_time", current_time); end end reflush_forbidden(); local ip = ngx_var.remote_addr; -- ngx.say(ip); -- ngx.say('<br>'); if forbidden:get(ip) then ngx_log(ngx_INFO, "forbidden ip refused access : ", ip); return ngx_exit(ngx.HTTP_FORBIDDEN); end
Comment here is closed