说起动态封禁IP,真是一个“明明做着很累,但总有人觉得你在摸鱼”的活儿。这次就和大家聊聊如何用Nginx来实现动态封禁IP,尤其是防止爬虫、恶意访问的场景。
先别急着皱眉,我会讲得清楚又风趣,带上代码示例,保证你轻松上手。
为什么要动态封禁IP?
核心需求总结:
封禁恶意请求:比如那些试图暴力破解、SQL注入的攻击者。 动态管理黑名单:自动化拉黑,不用手动更新配置文件。 封禁时间设置:可控时长,让被封禁的IP有“改过自新”的机会。
技术选型:Nginx + Lua + Redis
Nginx:作为反向代理,用它的性能处理高并发。 Lua:通过OpenResty框架,我们可以灵活编写动态逻辑。 Redis:存储IP黑名单,高效快速,支持过期时间。
环境配置
操作系统:CentOS 7 或 Ubuntu,其他主流发行版也行。 Redis:建议使用 5.0.5 或更高版本。 Nginx:推荐 Nginx-OpenResty,它让Lua配置更加方便。
示例环境安装(CentOS为例):
# 安装OpenResty
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
sudo yum install -y openresty
# 安装Redis
sudo yum install -y epel-release
sudo yum install -y redis
sudo systemctl start redis
sudo systemctl enable redis
配置实现
1. Nginx 配置
server
块中,添加Lua脚本的位置:http {
lua_shared_dict ip_blacklist 10m; # 定义共享字典存储黑名单
server {
listen 80;
location / {
access_by_lua_file /etc/nginx/lua/block_ip.lua;
proxy_pass http://backend;
}
}
}
2. Lua 脚本
获取用户IP。 检查IP是否在黑名单中。 如果IP访问频率超标,加入黑名单。 黑名单的封禁时间由Redis设置。
-- 引入Redis库
local redis = require "resty.redis"
-- 定义Redis连接函数
local function connect_redis()
local red = redis:new()
red:set_timeout(1000) -- 1秒超时
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "Failed to connect to Redis: ", err)
return nil
end
return red
end
-- 获取客户端IP
local client_ip = ngx.var.remote_addr
-- Redis存储逻辑
local red = connect_redis()
if not red then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
-- 检查是否在黑名单
local is_blocked = red:get("block:" .. client_ip)
if is_blocked == "1" then
ngx.exit(ngx.HTTP_FORBIDDEN) -- 返回403
end
-- 记录访问次数
local count, err = red:incr("count:" .. client_ip)
if not count then
ngx.log(ngx.ERR, "Failed to increment count: ", err)
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
-- 设置访问次数过期时间
if count == 1 then
red:expire("count:" .. client_ip, 10) -- 10秒过期
end
-- 如果超过阈值,加入黑名单
if count > 100 then
red:set("block:" .. client_ip, "1")
red:expire("block:" .. client_ip, 60) -- 封禁1分钟
ngx.exit(ngx.HTTP_FORBIDDEN)
end
工作原理小解析
IP 获取与检测:脚本中 ngx.var.remote_addr
直接获取客户端IP。Redis 计数:每次请求都会增加计数器,如果超出阈值,则将IP加入黑名单。 黑名单封禁:Redis的 expire
功能自动处理封禁时效,不需要我们操心。
优势分析
轻量级:Nginx和Lua结合,性能开销极小。 动态性强:IP黑名单动态更新,无需重启服务。 可扩展:只需修改脚本逻辑,就可以实现更复杂的规则,比如白名单、访问频率统计等。
应用场景扩展
防DDoS攻击:结合Nginx的限速模块。 防止数据滥用:比如对API接口进行访问频率限制。 异常检测:进一步扩展,可以接入日志分析系统。
X-Forwarded-For
头获取真实IP。-END-
以上,就是今天的分享了,看完文章记得右下角给何老师点赞,也欢迎在评论区写下你的留言。