How to Build a Dynamic IP Blacklist with Nginx, Lua, and Redis
This guide explains how to create a dynamic IP blacklist using Nginx, Lua scripts, and Redis, covering requirements, environment setup, design options, Nginx configuration, Lua implementation, summary of benefits, and possible extensions for advanced security scenarios.
Requirement
To block certain crawlers or malicious users, we need a dynamic IP blacklist that denies service to listed IPs and allows setting an expiration time for the ban.
Environment Preparation
Linux distribution: CentOS 7 / Ubuntu etc.
Redis version: 5.0.5
Nginx version: OpenResty
Design Scheme
There are three main ways to implement an IP blacklist:
Operating‑system level – configure iptables. Simple but requires manual changes on the server.
Web‑server level – use Nginx deny or Lua plugins for dynamic blocking. Flexible but needs Lua knowledge.
Application level – check the client IP in application code before processing the request. Easy to maintain but may affect performance under high concurrency.
We choose the Nginx + Lua + Redis architecture for easy management and sharing of the blacklist.
Configure nginx.conf
location / {
# If static resources, you can add a condition
#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; # apply rate‑limit logic
alias /usr/local/web/;
index index.html index.htm;
}Configure Lua Script
-- /usr/local/lua/access_limit.lua
local pool_max_idle_time = 10000 -- connection pool idle timeout (ms)
local pool_size = 100 -- connection pool size
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 -- block duration (seconds)
local ip_time_out = 1 -- time window for counting (seconds)
local ip_max_count = 3 -- max requests in the window
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
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 clientIP = getIp()
local incrKey = "limit:count:" .. clientIP
local blockKey = "limit:block:" .. clientIP
local is_block = client:get(blockKey)
if tonumber(is_block) == 1 then
ngx.exit(ngx.HTTP_FORBIDDEN)
close_redis(client)
end
local ip_count, err = 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
The Nginx + Lua + Redis solution provides a lightweight, easily configurable IP blacklist with minimal performance impact, supports sharing across multiple servers via Redis, and allows dynamic updates either manually or through automation.
Simple configuration with low overhead.
Shared blacklist across servers through Redis.
Dynamic updates possible via scripts or automation.
Extension
1. IP Blacklist Use Cases
Prevent malicious access – block IPs attempting brute‑force, SQL injection, XSS, etc.
Stop crawlers and data abuse – limit aggressive scraping.
Mitigate DDoS attacks – deny IPs launching large‑scale attacks.
Rate limiting – restrict request frequency from a single IP.
2. Advanced Features
Anomaly detection & auto‑ban – analyze logs to automatically block suspicious IPs.
Whitelist mechanism – allow trusted IPs to bypass the blacklist.
CAPTCHA verification – challenge high‑frequency IPs.
Statistics & analysis – track block counts, durations, and refine policies.
Continuous improvement of the IP blacklist enhances server and application security.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architect
Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
