Implementing a Dynamic IP Blacklist with Nginx, Lua, and Redis

This guide explains how to build a dynamic IP blacklist using Nginx, Lua, and Redis, covering installation of LuaJIT, compiling Nginx with required modules, configuring Redis, writing Lua access‑limit scripts, and verifying that frequent requests are automatically blocked for a set period.

Practical DevOps Architecture
Practical DevOps Architecture
Practical DevOps Architecture
Implementing a Dynamic IP Blacklist with Nginx, Lua, and Redis

To prevent malicious crawlers or abusive users from accessing a server, a dynamic IP blacklist is required that rejects requests from IPs listed in the blacklist.

There are several ways to implement an IP blacklist: configuring iptables at the OS level, using Nginx's deny directive or Lua plugins, or checking the client IP in the application layer. This article adopts the Nginx + Lua + Redis architecture to create a Web Application Firewall (WAF) that dynamically blocks frequent IPs.

Install LuaJIT :

[root@hd03 ~]# tar -xf LuaJIT-2.0.5.tar.gz -C /opt/
[root@hd03 ~]# cd /opt/LuaJIT-2.0.5/
[root@hd03 LuaJIT-2.0.5]# make && make install

Set environment variables:

export LUAJIT_LIB=/usr/local/lib
export LUAJIT_INC=/usr/local/include/luajit-2.0

Source the profile and create a symlink for the shared library.

[root@hd03 LuaJIT-2.0.5]# source ~/.bash_profile
[root@hd03 LuaJIT-2.0.5]# ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2

Compile Nginx with required modules (including Lua and Redis support):

[root@hd03 ~]# tar -xf nginx-1.20.2.tar.gz -C /opt/
[root@hd03 nginx-1.20.2]# ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --sbin-path=/usr/local/nginx/bin/nginx --conf-path=/usr/local/nginx/conf/nginx.conf --pid-path=/usr/local/nginx/logs/nginx.pid --lock-path=/usr/local/nginx/run/nginx.lock --error-log-path=/usr/local/nginx/logs/error.log --http-log-path=/usr/local/nginx/logs/access.log --http-client-body-temp-path=/var/cache/client_temp --http-proxy-temp-path=/var/cache/proxy_temp --http-fastcgi-temp-path=/var/cache/fastcgi_temp --http-uwsgi-temp-path=/var/cache/uwsgi_temp --http-scgi-temp-path=/var/cache/scgi_temp --with-http_v2_module --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-mail --with-mail_ssl_module --with-file-aio --with-threads --with-stream --with-stream_ssl_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --add-module=/usr/local/ngx_devel_kit-0.3.0 --add-module=/usr/local/lua-nginx-module-0.10.13
[root@hd03 nginx-1.20.2]# make && make install
[root@hd03 nginx-1.20.2]# ln -s /usr/local/nginx/bin/nginx /usr/bin/

Start Nginx: [root@hd03 nginx-1.20.2]# nginx Deploy the WAF components :

Install lua-resty-redis module:

[root@hd03 ~]# cd /usr/local/lua-resty-redis
[root@hd03 lua-resty-redis]# make && make install

Install and configure Redis : [root@hd03 ~]# yum install redis -y Modify /etc/redis.conf (example settings):

bind 0.0.0.0
daemonize yes
logfile /var/log/redis/redis.log
requirepass 123456
dir /data/redis

Update Nginx configuration to use the WAF :

lua_shared_dict limit 8m;
lua_package_path "lua;/usr/local/nginx/conf/waf/redis.lua;;";

Create access_limit.lua (the script checks request frequency, stores counters in Redis, and adds offending IPs to the blacklist).

Place the script in /usr/local/nginx/conf/waf and test the configuration: [root@hd03 waf]# nginx -t Result:

nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

Reload Nginx: [root@hd03 waf]# nginx -s reload When a client refreshes the site more than 10 times within one minute, the IP is cached in Redis and automatically blocked for 5 minutes, returning a 403 status code.

Verify in Redis:

Check request count:

redis-cli -h 192.167.16.8 -a 123456
get USER-COUNT-192.167.16.8

→ "9" (means 9 hits cached).

Retrieve blacklist set: smembers limit:ip:blacklist → "192.167.16.8".

Manually add an IP to the blacklist: sadd limit:ip:blacklist 192.167.16.8 This completes the end‑to‑end setup of a dynamic IP blacklist using Nginx, Lua, and Redis.

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.

BackendredisNginxLuaWAFip blacklist
Practical DevOps Architecture
Written by

Practical DevOps Architecture

Hands‑on DevOps operations using Docker, K8s, Jenkins, and Ansible—empowering ops professionals to grow together through sharing, discussion, knowledge consolidation, and continuous improvement.

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.