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.
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.
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.
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.