屏蔽非法IP的核心是行为识别而非特征匹配,Nginx通过日志分析(如高频404、异常UA、短时密集请求)、geo+map动态黑名单、limit_req限流标记及OpenResty+Lua+Redis实时封禁四层机制实现精准拦截。

屏蔽带有非法行为特征的 IP,关键不是“认出它长什么样”,而是“发现它做了什么”。Nginx 本身不分析内容语义(比如识别“爬虫伪装成浏览器”或“SQL注入关键词”),但它能基于请求行为、频率、来源和响应结果,结合日志与外部工具,精准定位并拦截这类 IP。核心思路是:先识别特征 → 再归类标记 → 最后执行封禁。
从访问日志中识别非法行为特征
真实攻击 IP 往往在日志里留下明显痕迹,例如高频 404、大量 POST 到非接口路径、User-Agent 异常、短时间密集请求等。可直接用命令快速筛查:
- 高频 404 扫描者:`awk '$9 == 404 {print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20`
- 异常 User-Agent:`grep -E "(sqlmap|nikto|dirbuster|curl.*\-\-user\-agent)" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c`
- 短时高频请求(如 1 秒内 >10 次):需配合 `limit_req` 日志记录,或用脚本按 `$remote_addr` 和 `$time_local` 统计窗口内请求数
用 geo + map 实现轻量级动态黑名单
适合定时更新(如每小时跑一次封禁脚本),无需重启 Nginx,配置干净且兼容原生环境:
- 新建文件 /etc/nginx/conf.d/blocklist.conf,内容为:
default 0;<br>192.168.1.100 1;<br>203.0.113.45 1;
- 在 http 块中添加:
geo $bad_ip {<br> default 0;<br> include /etc/nginx/conf.d/blocklist.conf;<br>}map $bad_ip $deny_flag {<br> 1 "1";<br> default ""; <br>} - 在 server 或 location 中加入:
if ($deny_flag) { return 403; }
用 limit_req 配合日志实现自动限流+标记
对疑似暴力破解、CC 攻击等行为,先限流再标记,避免误伤正常用户:
- 定义请求限制区域:
limit_req_zone $binary_remote_addr zone=abuse:10m rate=5r/s burst=10 nodelay; - 在 location 中启用,并记录被限流的 IP:
limit_req zone=abuse; <br>limit_req_log_level warn;
- 配置日志格式,让被限流请求带标识:
log_format main '$remote_addr – $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time $limit_req_status';
其中 $limit_req_status 为 “rejected” 即表示触发了限流 - 后续可通过日志提取 rejected 行中的 IP,自动追加进 blocklist.conf 并 reload
高阶方案:OpenResty + Lua + Redis 实时封禁
适用于需要毫秒级响应、支持临时封禁(如 5 分钟)、多节点共享黑名单的生产环境:
- 使用 access_by_lua_block 在请求入口检查 Redis 中该 IP 是否在黑名单;
- 若命中,直接 ngx.exit(403);
- 同时在 Lua 中统计请求频次,当单位时间内超阈值(如 30 秒内 50 次 POST),自动写入 Redis 并设置过期时间(如 redis.expire(key, 300));
- 所有 Nginx 节点共用同一 Redis,实现集群级实时封禁


















