连续复制
一键复制
一键打包

http声明

lua_shared_dict limit_store 30m;  # 存储限流状态的共享内存
lua_shared_dict blackip_store 30m;  # 存储黑名单的共享内存
lua_package_path "/www/server/nginx/?.lua;;";  # 更新路径以包含你的 Lua 文件

服务配置

   location /blackip {
      content_by_lua_block {
          local limit = require "limit"  -- 引入 blackip_check.lua 文件
          limit.check_blackip()  -- 调用检查黑名单的函数
      }
    }

    location / {
        access_by_lua_block {
            local limit = require "limit"  -- 引入 limit.lua 文件
            limit.check_limit()  -- 调用检查限流和黑名单的函数
        }
    }

limit.lua

-- limit.lua

local _M = {}

function _M.check_blackip()
    ngx.header.content_type = "text/plain"  -- 设置返回类型为文本

    local blackip = ngx.shared.blackip_store
    local ip = ngx.var.arg_ip or ngx.var.remote_addr  -- 如果存在 ip 参数则使用,否则使用当前请求的 IP

    if blackip:get(ip) then
        ngx.say("IP " .. ip .. " is blackiped")
    else
        ngx.say("IP " .. ip .. " is not blackiped")
    end
end

function _M.check_limit()
    local blackip = ngx.shared.blackip_store
    local key = ngx.var.remote_addr

    -- 检查是否在黑名单中
    if blackip:get(key) then
        return ngx.exit(403)  -- 返回 403 禁止访问
    end

    local limit_req = require "resty.limit.req"
    local lim, err = limit_req.new("limit_store", 60, 1)  -- 每分钟 60 次请求

    if not lim then
        ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req: ", err)
        return ngx.exit(500)
    end

    local res, err = lim:incoming(key, true)

    if not res then
        if err == "rejected" then
            -- 触发限流,加入黑名单
            blackip:set(key, true, 3600)  -- 加入黑名单 1 小时
            return ngx.exit(403)
        end
        return ngx.exit(500)
    end
end

return _M