Nginx、Lua 和 Redis 架构来实现 IP 黑名单
需求
为了封禁某些爬虫或者恶意用户对服务器的请求,我们需要建立一个动态的 IP 黑名单。对于黑名单中的 IP ,我们将拒绝提供服务。并且可以设置封禁失效时间
环境准备
● linux version: centos7 / ubuntu 等
● redis version: 5.0.5
● nginx version: nginx-openresty
设计方案
实现 IP 黑名单的功能有很多途径:
1、在操作系统层面,配置 iptables,来拦截指定 IP 的网络请求。
● 优点:简单直接,在服务器物理层面上进行拦截
● 缺点:每次需要手动上服务器修改配置文件,操作繁琐且不灵活
2、在 Web 服务器层面,通过 Nginx 自身的 deny 选项或者 lua 插件配置 IP 黑名单。
● 优点:可动态实现封禁 ip,通过设置封禁时间可以做到分布式封禁
● 缺点:需要了解 Lua 脚本和 Nginx 配置,有一定的学习成本
3、在应用层面,在处理请求之前检查客户端的 IP 地址是否在黑名单中。
● 优点:通过编写代码来实现,相对简单且易于维护。
● 缺点:代码可能会变得冗长,而且在高并发情况下可能影响性能。
为了方便管理和共享黑名单,通过 nginx + lua + redis 的架构实现 IP 黑名单的功能
实现详解
使用 Nginx、Lua 和 Redis 架构来实现 IP 黑名单功能,是一个强大且灵活的解决方案。下面是一个基本的实现步骤,帮助你理解如何设置和使用这一架构。
前提条件
- Nginx 已安装并配置好。
- LuaJIT 已安装并配置在 Nginx 中(通常通过 ngx_lua 模块)。
- Redis 已安装并运行。
步骤 1:安装 Nginx 和 Lua 模块 - 安装 Nginx(如果还没有安装):
sudo apt-get update
sudo apt-get install nginx
2. 安装 LuaJIT(如果还没有安装):
sudo apt-get install luajit
3. 安装 ngx_lua 模块(例如通过 openresty 包):
sudo apt-get install openresty
步骤 2:配置 Nginx
编辑 Nginx 配置文件(例如 /etc/nginx/nginx.conf 或 /etc/openresty/nginx.conf),以启用 Lua 脚本处理。
- 加载 Lua 模块:
http {
lua_shared_dict my_cache 10m;
lua_package_path "/usr/local/openresty/lualib/?.lua;;";
server {
listen 80;
location / {
access_by_lua_file /etc/nginx/lua/blacklist.lua;
proxy_pass http://your_backend;
}
}
}
步骤 3:编写 Lua 脚本
在 /etc/nginx/lua/ 目录下创建一个名为 blacklist.lua 的文件,并添加以下内容:
-- blacklist.lua
local redis = require "resty.redis"
local red = redis:new()
-- 配置 Redis 服务器信息
red:set_timeout(1000) -- 1 sec
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.say("failed to connect: ", err)
return ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE)
end
-- 获取客户端 IP 地址
local client_ip = ngx.var.remote_addr
-- 从 Redis 中获取黑名单 IP 列表
local res, err = red:smembers("blacklist_ips")
if not res then
ngx.say("failed to get blacklist: ", err)
return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
-- 检查客户端 IP 是否在黑名单中
if res and #res > 0 then
for _, ip in ipairs(res) do
if client_ip == ip then
ngx.say("Access Forbidden. Your IP is blacklisted.")
return ngx.exit(ngx.HTTP_FORBIDDEN)
end
end
end
– 如果 IP 不在黑名单中,继续处理请求
步骤 4:配置 Redis 黑名单
你可以手动将 IP 地址添加到 Redis 的黑名单集合中:
sh复制代码
redis-cli
SADD blacklist_ips 192.168.1.100
(integer) 1
步骤 5:重启 Nginx
在配置完所有内容后,重启 Nginx 以使配置生效:
sudo systemctl restart nginx
sudo nginx -s reload
测试
使用浏览器或 curl 访问你的 Nginx 服务器,看看访问是否被阻止:
curl -I http://your_server_ip_or_domain
如果 IP 地址在黑名单中,你应该会看到 HTTP 状态码 403 Forbidden 和一条消息 “Access Forbidden. Your IP is blacklisted.”。
进一步优化
- 缓存 Redis 查询结果:为了减少 Redis 查询次数,可以将查询结果缓存到 Nginx 的共享字典中。
- 动态更新黑名单:可以开发一个 Web 接口来动态添加或删除黑名单 IP。
- 日志记录:记录被阻止的访问尝试,以便进行进一步分析。
通过上述步骤,你应该能够成功使用 Nginx、Lua 和 Redis 实现一个基本的 IP 黑名单功能。
动态管理黑名单
为了动态管理黑名单,可以创建一个简单的 API 接口来添加或删除 IP 地址,这样可以通过 HTTP 请求来更新 Redis 中的黑名单。
IP 黑名单的应用场景
IP 黑名单在实际应用中具有广泛的应用场景,主要用于保护服务器和应用免受恶意攻击、爬虫或滥用行为的影响。下面列举几个常见的应用场景:
● 防止恶意访问: 黑名单可以阻止那些试图通过暴力破解密码、SQL 注入、XSS 攻击等方式进行非法访问的 IP 地址。
● 防止爬虫和数据滥用: 黑名单可以限制那些频繁访问网站并抓取大量数据的爬虫,以减轻服务器负载和保护数据安全。
● 防止 DDOS 攻击: 黑名单可以封禁那些发起大规模DDoS攻击的IP地址,保护服务器的稳定性和安全性。
● 限制访问频率: 黑名单可以限制某个IP在特定时间段内的访问次数,防止恶意用户进行暴力破解、刷票等行为。
2、高级功能和改进
除了基本的 IP 黑名单功能外,还可以进行一些高级功能和改进,以提升安全性和用户体验:
● 异常检测和自动封禁: 通过分析访问日志和行为模式,可以实现异常检测功能,并自动将异常行为的 IP 地址封禁,提高安全性。
● 白名单机制: 除了黑名单,还可以引入白名单机制,允许某些 IP 地址绕过黑名单限制,确保合法用户的正常访问。
● 验证码验证: 对于频繁访问或异常行为的 IP,可以要求其进行验证码验证,以进一步防止恶意行为。
● 数据统计和分析: 将黑名单相关的数据进行统计和分析,例如记录封禁 IP 的次数、持续时间等信息,以便后续优化和调整策略。
通过不断改进和优化 IP 黑名单功能,可以更好地保护服务器和应用的安全。