Basic WAF example using lua + redis within nginx.

--
--   lua_package_path "/usr/share/lua/5.1/nginx/?.lua;;";
--   lua_shared_dict ip_blacklist 4m;
--
local redis_host               = "your.redis.tld"
local redis_port               = 6379
local redis_connection_timeout = 300
local redis_pattern            = "block-"
local cache_ttl                = 3 -- seconds
local ip                       = ngx.var.remote_addr
local ip_blacklist             = ngx.shared.ip_blacklist
local last_update_time         = ip_blacklist:get("last_update_time");

-- block if ip found in the local nginx dict
if ip_blacklist:get(ip) then
    ngx.log(ngx.DEBUG, "Banned IP detected and refused access: " .. ip);
    return ngx.exit(429);
end

-- only update ip_blacklist from Redis once every cache_ttl seconds:
if last_update_time == nil or last_update_time < ( ngx.now() - cache_ttl ) then
    local redis = require "redis";
    local red = redis:new();

    red:set_timeout(redis_connect_timeout);

    local ok, err = red:connect(redis_host, redis_port);
    if not ok then
        ngx.log(ngx.DEBUG, "Redis connection error while retrieving ip_blacklist: " .. err);
    else
        local res, err = red:get(redis_pattern .. ip);
        if err then
            ngx.log(ngx.DEBUG, "Redis read error while retrieving ip_blacklist: " .. err);
            return
        end
        if res ~= ngx.null then
            local ttl, err = red:ttl(redis_pattern .. ip);
            if not ttl then
                ngx.log(ngx.DEBUG, "Redis connection error while retrieving ttl" .. err);
                return
            end
            -- add IP to the ip_blacklist dict inheriting the TTL form redis
            ip_blacklist:set(ip, true, ttl);
            ip_blacklist:set("last_update_time", ngx.now());
        end
    end
end

In nginx add this lines:

resolver 10.10.0.2 valid=10s; # depends on your redis host
lua_package_path "/usr/share/lua/5.1/nginx/?.lua;/etc/nginx/lua/?.lua;;";
lua_shared_dict ip_blacklist 4m;

And call the scrip in the server section:


server {
    listen 80;
    server_name _;
    access_by_lua_file /etc/nginx/lua/ip_blacklist.lua;
    ...
}

In Linux (ubuntu) this may be required:

apt install nginx-extras lua-nginx-redis