How to Build a Dynamic IP Blacklist with Nginx, Lua, and Redis

This guide explains how to create a dynamic IP blacklist that blocks malicious crawlers and users by configuring Nginx with Lua scripts and a Redis store, covering requirements, environment setup, design options, configuration files, Lua code, summary of benefits, use cases, and advanced extensions.

Su San Talks Tech
Su San Talks Tech
Su San Talks Tech
How to Build a Dynamic IP Blacklist with Nginx, Lua, and Redis

Requirement

To block certain crawlers or malicious users, we need a dynamic IP blacklist that rejects requests from listed IPs and can set expiration times.

Environment Preparation

Linux (CentOS7 / Ubuntu etc.)

Redis 5.0.5

Nginx (OpenResty)

Design方案

There are three ways to implement an IP blacklist:

OS level using iptables – simple but requires manual updates.

Web server level using Nginx deny or Lua plugin – dynamic but requires Lua knowledge.

Application level checking IP before processing – easy to code but may affect performance under high concurrency.

We choose the Nginx + Lua + Redis architecture for dynamic management.

Architecture diagram
Architecture diagram

Configure nginx.conf

location / {
    # if ($request_uri ~ .*\.(html|htm|jpg|js|css)) {
    #     access_by_lua_file /usr/local/lua/access_limit.lua;
    # }
    access_by_lua_file /usr/local/lua/access_limit.lua;
    alias /usr/local/web/;
    index index.html index.htm;
}

Configure Lua script

-- /usr/local/lua/access_limit.lua
local pool_max_idle_time = 10000
local pool_size = 100
local redis_connection_timeout = 100
local redis_host = "your redis host ip"
local redis_port = "your redis port"
local redis_auth = "your redis authpassword"
local ip_block_time = 120
local ip_time_out = 1
local ip_max_count = 3

local function errlog(msg, ex)
    ngx.log(ngx.ERR, msg, ex)
end

local function close_redis(red)
    if not red then return end
    local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)
    if not ok then
        ngx.say("redis connct err:", err)
        return red:close()
    end
end

local redis = require "resty.redis"
local client = redis:new()
local ok, err = client:connect(redis_host, redis_port)
if not ok then
    close_redis(client)
    ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
client:set_timeout(redis_connection_timeout)

local connCount, err = client:get_reused_times()
if connCount == 0 then
    local ok, err = client:auth(redis_auth)
    if not ok then errlog("failed to auth: ", err); return end
elseif err then
    errlog("failed to get reused times: ", err); return
end

local function getIp()
    local clientIP = ngx.req.get_headers()["X-Real-IP"]
    if not clientIP then clientIP = ngx.req.get_headers()["x_forwarded_for"] end
    if not clientIP then clientIP = ngx.var.remote_addr end
    return clientIP
end

local cliendIp = getIp()
local incrKey = "limit:count:" .. cliendIp
local blockKey = "limit:block:" .. cliendIp

local is_block = client:get(blockKey)
if tonumber(is_block) == 1 then
    ngx.exit(ngx.HTTP_FORBIDDEN)
    close_redis(client)
end

local ip_count = client:incr(incrKey)
if tonumber(ip_count) == 1 then
    client:expire(incrKey, ip_time_out)
end

if tonumber(ip_count) > tonumber(ip_max_count) then
    client:set(blockKey, 1)
    client:expire(blockKey, ip_block_time)
end

close_redis(client)

Summary

Simple, lightweight configuration with minimal performance impact.

Multiple servers can share the blacklist via a common Redis instance.

Dynamic updates can be made manually or through automation.

Extensions

Application scenarios

Prevent malicious access such as brute‑force, SQL injection, XSS.

Block crawlers and data abuse.

Mitigate DDoS attacks.

Rate‑limit requests from a single IP.

Advanced features

Automatic anomaly detection and banning.

Whitelist mechanism for trusted IPs.

Captcha verification for suspicious traffic.

Statistics and analysis of blacklist data.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backend DevelopmentredisSecurityNGINXLuaip blacklist
Su San Talks Tech
Written by

Su San Talks Tech

Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.