Nginx 动态封禁 IP 实战:从配置到落地全流程
构建动态IP黑名单:Nginx+Lua+Redis实战方案
服务器时不时遭遇恶意爬虫或攻击者的频繁请求,怎么办?一个行之有效的防御策略是建立动态的IP黑名单。简单说,就是把那些“不受欢迎”的IP地址列入名单,在一段时间内拒绝其所有访问请求。这不仅能有效拦截恶意流量,还能灵活设置封禁时长,实现自动化管理。
免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
需求与环境准备
我们的目标很明确:搭建一个能够动态更新、支持分布式共享、且对应用性能影响极小的IP黑名单系统。在开始动手前,需要准备好以下环境:
服务器系统: CentOS 7 或 Ubuntu 等主流Linux发行版均可。
Redis版本: 5.0.5 或更高。
Nginx版本: 推荐使用集成Lua模块的OpenResty,它让在Nginx中嵌入Lua逻辑变得轻而易举。
设计方案选型
实现IP黑名单,路子其实不少,各有优劣:
1. 操作系统层面(如iptables)
直接在服务器防火墙上动手。优点是拦截彻底,效果立竿见影。但缺点也很明显:每次操作都得登录服务器手动修改配置,既麻烦又难以应对快速变化的攻击,更别提在多台服务器间同步名单了。
2. Web服务器层面(如Nginx)
利用Nginx自身的deny指令或强大的Lua扩展模块。这个方案的魅力在于“动态化”——可以通过程序逻辑实时更新黑名单,并能方便地设置过期时间。一套配置可以分发到多台Nginx服务器,实现分布式封禁。当然,它需要你稍微了解一下Lua脚本和Nginx配置。
3. 应用层面
在业务代码处理请求前,先检查IP是否在黑名单里。这种方式对开发者最友好,容易理解和维护。但问题在于,它增加了应用的逻辑负担,在高并发场景下可能成为性能瓶颈,而且代码容易变得冗长。
综合来看,为了兼顾灵活性、性能和易管理性,Nginx + Lua + Redis的组合脱颖而出。它利用Redis作为中心化的存储和共享点,通过Lua脚本在Nginx的访问阶段进行高效判断,几乎不影响正常业务响应速度。
上图清晰地展示了这个工作流程:请求到达Nginx,由Lua脚本查询Redis中的黑名单,并决定是放行还是拒绝。
配置nginx.conf
配置起来并不复杂。首先,在你需要启用IP黑名单的站点配置中,找到对应的location块,加入一行Lua脚本调用即可。
location / {
# 如果该location下存在静态资源文件,可以考虑做个判断,避免对静态资源也进行黑名单校验
# 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; # 关键配置,引入Lua限流脚本
alias /usr/local/web/;
index index.html index.htm;
}
这里有个小技巧:如果你的这个location主要存放图片、CSS等静态文件,且攻击主要针对动态接口,可以用if判断(注释部分所示)来减少不必要的Redis查询,进一步提升性能。不过,对于大多数场景,直接全局启用也没问题。
编写核心Lua脚本
接下来是重头戏:编写/usr/local/lua/access_limit.lua脚本。这个脚本负责具体的封禁逻辑,其核心思想是:在单位时间内,如果某个IP的访问次数超过阈值,则将其加入黑名单一段时间。
-- access_limit.lua
-- 目标:自动将访问过频的IP加入黑名单封禁一段时间
-- ---------- 配置区 ----------
local pool_max_idle_time = 10000 -- Redis连接池超时回收时间(毫秒)
local pool_size = 100 -- Redis连接池大小
local redis_connection_timeout = 100 -- Redis连接超时时间(毫秒)
local redis_host = "your redis host ip" -- Redis服务器地址
local redis_port = "your redis port" -- Redis端口
local redis_auth = "your redis auth password" -- Redis认证密码
local ip_block_time = 120 -- IP被封禁的时长(秒)
local ip_time_out = 1 -- 统计访问频率的时间窗口(秒)
local ip_max_count = 3 -- 时间窗口内允许的最大访问次数
-- ---------- 配置结束 ----------
-- 记录错误日志
local function errlog(msg, ex)
ngx.log(ngx.ERR, msg, ex)
end
-- 将Redis连接归还至连接池
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 connect err:", err)
return red:close()
end
end
-- 连接Redis
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) -- 连接失败,返回500错误
end
-- 设置超时
client:set_timeout(redis_connection_timeout)
-- 优化:只有新建的连接才需要认证密码
local connCount, err = client:get_reused_times()
if 0 == connCount then
local 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
-- 获取客户端真实IP(考虑袋里情况)
local function getIp()
local clientIP = ngx.req.get_headers()["X-Real-IP"]
if clientIP == nil then
clientIP = ngx.req.get_headers()["x_forwarded_for"]
end
if clientIP == nil then
clientIP = ngx.var.remote_addr
end
return clientIP
end
local clientIp = getIp();
local incrKey = "limit:count:" .. clientIp -- 用于计数器的Key
local blockKey = "limit:block:" .. clientIp -- 用于标记是否封禁的Key
-- 检查IP是否已被封禁
local is_block, err = client:get(blockKey)
if tonumber(is_block) == 1 then
ngx.exit(ngx.HTTP_FORBIDDEN) -- 如果已被封禁,直接返回403
close_redis(client)
end
-- IP访问计数:每次访问+1,如果是首次(值为1),设置计数器过期时间
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)
这个脚本的逻辑链条非常清晰:获取IP -> 查是否已封禁 -> 统计访问次数 -> 判断是否触发封禁。所有状态都存储在Redis中,因此多台Nginx服务器可以共享同一份黑名单,实现了分布式防护。
方案总结
至此,一个基于Nginx+Lua+Redis的动态IP黑名单系统就搭建完成了。回顾一下,这个方案有几个突出的优点:
1. 轻量高效: 在Nginx的访问阶段进行拦截,对后端应用服务几乎无感,性能损耗极小。
2. 集中管理: 通过Redis集中存储黑名单,任何服务器上的策略变更都能实时同步,管理起来非常方便。
3. 动态灵活: 封禁策略(如时间窗口、阈值、封禁时长)可以通过修改Lua脚本或Redis数据动态调整,无需重启服务。
扩展思考
1. IP黑名单的典型应用场景
这个功能可不是简单的“关门谢客”,它在多种安全防护场景下都能大显身手:
防御恶意扫描与攻击: 有效拦截那些进行密码暴力破解、SQL注入、XSS跨站脚本测试的IP源。
反爬虫与数据保护: 限制恶意爬虫高频抓取数据,既能减轻服务器负载,也能保护核心数据资产。
缓解DDoS攻击: 虽然无法应对海量分布式攻击,但对于小规模或持续性的攻击源,将其IP加入黑名单可以快速切断流量,为其他防护措施争取时间。
业务风控: 例如,限制同一IP在秒杀活动中的抢购次数,或者在投票系统中防止刷票。
2. 高级功能与优化方向
基础功能实现后,还可以在此基础上做更多文章,让防护体系更智能、更健壮:
智能异常检测与自动封禁: 结合日志分析,可以建立更复杂的模型。例如,不仅检测访问频率,还分析访问路径、User-Agent等特征,自动识别并封禁有异常行为的IP。
引入白名单机制: 有黑就有白。将可信的IP(如公司出口IP、合作伙伴IP)加入白名单,确保其访问永远不会被误拦截,这对于运维和内部测试至关重要。
验证码挑战: 对于可疑但又不确定是恶意攻击的IP(例如频率略高于阈值),可以不直接封禁,而是弹出验证码进行人机验证。通过则正常访问,失败则加入黑名单。
数据统计与分析: 将黑名单的触发记录、封禁时长、IP来源等信息进行统计和分析。这些数据是优化防护策略的宝贵依据,能帮你回答诸如“攻击主要来自哪个地区?”“哪种攻击模式最常见?”等问题。
安全防护是一个持续的过程。通过不断迭代和优化IP黑名单策略,你可以为服务器和应用构筑起一道更加灵活、智能的动态防线。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
什么是RPA?为什么用RPA?RPA如何工作?
什么是RPA 简单来说,RPA是一种在商业逻辑与规则控制下,用来精简和优化流程的自动化系统。我们常把它比作一位不知疲倦的“数字员工”,专门用来高效处理那些重复性强、规则明确的任务。想一想后台办公室的场景:许多具备平均知识水平的员工,每天不得不花费大量时间在冗长、乏味且令人厌倦的例行程序上。RPA工具
不破不立,让RPA像Excel一样方便易用
RPA:从“专家可用”到“人人可用”,一道亟待跨越的鸿沟 提到RPA(机器人流程自动化),很多人的第一印象是“非侵入式”和“高效”。确实,这项技术能在不改造原有系统的前提下,为企业实现流程自动化,单凭这一点就赢得了大量青睐。但它的魅力远不止于此。 它的可扩展性和灵活性,让它能够适配千行百业的数字化转
RPA技术在营销业务中的应用案例
RPA技术在营销业务中的应用案例 (1)智能停电全流程机器人 公变用户的停电流程,过去是个典型的“磨人”活。每天要重复登录好几个系统,处理异常派单,还得不停地和现场人员电话沟通,手动核对、搜索各种信息。这一套组合拳打下来,不仅耗费大量人力,更头疼的是,一旦遇到人员流动或者手一抖出了操作误差,公变停电
RPA技术的概念、优势和技术架构
概念 说起机器人流程自动化(RPA),它其实是一种利用“软件机器人”来代劳那些高度重复性工作的技术。简单理解,它就是在你电脑里运行的一个程序,或者说一个虚拟的“数字员工”。它的核心任务,就是模拟人类与计算机的交互方式,把那些繁琐、复杂又量大的事务性工作承接过来,从而在降低人力成本的同时,大幅提升整体
基于RPA的财务共享服务中心资金管理系统框架
(一)RPA是什么 RPA,也就是机器人流程自动化,是近年来在人工智能浪潮下兴起的一门自动化技术。简单说,它就像一个不知疲倦的“数字员工”,能够通过预设好的程序,模拟并执行我们人类在电脑上的各种操作。无论是登录系统、复制粘贴数据,还是核对报表,它都能一丝不苟地完成。 它的优势非常突出:可以按照设定7
- 日榜
- 周榜
- 月榜
1
2
3
4
5
6
7
8
9
10
相关攻略
2015-03-10 11:25
2015-03-10 11:05
2021-08-04 13:30
2015-03-10 11:22
2015-03-10 12:39
2022-05-16 18:57
2025-05-23 13:43
2025-05-23 14:01
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

