Nginx 动态封禁 IP

内容分享7天前发布
0 0 0

问题:最近在工作中遇到了一些问题,站点有大量的流量消耗,但是并没有有效转化,通过排查发现很多无效IP和爬虫IP一直再访问站点,浪费了流量又占用了服务器资源。

解决:在 Nginx 中实现动态封禁 IP,可以有效保护网站或应用免受恶意请求、爬虫或 DDoS 攻击。相比于传统的修改配置文件 + 重载 Nginx 的静态方式,动态封禁能够自动识别、实时阻断恶意 IP,大大提升安全性和运维效率。

 动态封禁 IP 的常用方案:

方案类型 实现方式 优点 缺点 适用场景
Fail2ban 工具 监控 Nginx 日志,达到阈值后调用防火墙或修改配置封禁 配置简单,社区成熟,支持多种服务 依赖日志分析,有延迟,频繁重载影响性能 防暴力破解、扫描器、异常请求攻击
Nginx Lua + Redis 使用 ngx_lua 在访问阶段查询 Redis 黑名单 性能高,实时生效,可分布式共享 需要 OpenResty/Lua,架构复杂 高并发场景,分布式共享黑名单,精细化策略
 
Nginx 内置模块 limit_req_zone 和 limit_conn_zone 限制请求频率和并发 原生支持,无需第三方依赖 仅限流/限连接,不能真正封禁 防 CC 攻击、防止单 IP 滥用

各方案配置要点

一、使用 Fail2ban 动态封禁

Fail2ban 通过监控 Nginx 日志(如 403/401/404 错误码、访问过于频繁的 IP),动态调用 iptables 或 firewalld 进行封禁。

核心步骤:

1、安装 Fail2ban



sudo apt-get install fail2ban    # Debian/Ubuntu
sudo yum install fail2ban        # CentOS/RHEL

2.配置 Nginx 日志



log_format main '$remote_addr - $remote_user [$time_local] "$request" '                
				'$status $body_bytes_sent "$http_referer" '                
				'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;   ###根据你的实际日志文件路径修改

3.创建过滤规则 /etc/fail2ban/filter.d/nginx-cc.conf



[Definition]
failregex = ^<HOST> -.*"(GET|POST).*HTTP.*" 403
ignoreregex =

4.配置 Jail /etc/fail2ban/jail.local



[nginx-cc]
enabled = true
port = http,https
filter = nginx-cc
logpath = /var/log/nginx/access.log
maxretry = 100
findtime = 60
bantime = 3600
action = iptables[name=NGINX, port=http, protocol=tcp]

5.启动服务



sudo systemctl enable fail2ban
sudo systemctl restart fail2ban

二、使用 Nginx Lua + Redis 动态封禁

此方案依赖 OpenResty(集成了 Nginx + LuaJIT),在请求到达时即时查询 Redis 黑名单,效率极高。

核心步骤:

1.安装 OpenResty



sudo yum install yum-utils
sudo yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
sudo yum install openresty

2.配置 Nginx



http {    
	lua_shared_dict ip_blacklist 10m;
	server {
		listen 80;        
		location / {            
			access_by_lua_file /etc/nginx/lua/ip_blacklist.lua;        
		}    
	}
}

3.编写 Lua 脚本 /etc/nginx/lua/ip_blacklist.lua



local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000)
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then    
	ngx.log(ngx.ERR, "Redis connection failed: ", err)    
	return
end
 
local client_ip = ngx.var.remote_addr
local is_banned = red:sismember("ip_blacklist", client_ip)
if is_banned == 1 then    
	ngx.exit(ngx.HTTP_FORBIDDEN)
end
 
red:set_keepalive(10000, 100)

4.管理黑名单



redis-cli SADD ip_blacklist 192.168.1.100   # 封禁
redis-cli SREM ip_blacklist 192.168.1.100   # 解封

三、使用 Nginx 内置模块限流

Nginx 自带 limit_req_zone 和 limit_conn_zone,可限制请求速率与连接数。虽不能真正封禁,但能有效缓解 CC 攻击。

配置示例:



http {
    limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
    server {
        location / {
            limit_req zone=req_limit burst=20 nodelay;
            limit_conn conn_limit 10;
        }
    }
}

效果:超限请求返回 503 Service Temporarily Unavailable


实战经验与注意事项:

1.确保获取真实 IP

  在有 CDN/代理的情况下,记得配置:



set_real_ip_from  0.0.0.0/0;
real_ip_header    X-Forwarded-For;
real_ip_recursive on;

2.组合拳效果更佳

  Fail2ban → 封禁恶意行为 IP。
  Nginx 内置限流 → 防瞬时高频攻击。
  Lua + Redis → 分布式实时黑名单。

3.封禁策略要分层

  瞬时保护:limit_req/limit_conn。
  短期封禁:Fail2ban(分钟 ~ 小时)。
  长期全局封禁:Lua + Redis(天级甚至永久)。


总结:

在 Nginx 中实现动态封禁 IP,主要有三种方式:

        Fail2ban:日志驱动,适合单机和简单场景;

        Nginx Lua + Redis:高性能实时黑名单,适合分布式和大规模业务;

        Nginx 内置模块:原生限流/限连,适合应对 CC 攻击。

推荐实战落地:

        单机 → Fail2ban + 内置限流

        分布式/高并发 → Lua + Redis + 内置限流

这样既能快速见效,又能兼顾长期扩展性

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...