Nginx可通过自定义log_format、map模块标记异常请求、logrotate+脚本分析及fail2ban联动实现异常IP识别与封禁,需注意代理环境下真实IP获取(set_real_ip_from+realip模块)。

在 Nginx 中记录并分析异常访问 IP,核心是结合日志配置、条件过滤与外部工具(或简单脚本)实现识别与归因。不需要额外模块,原生功能即可支撑大部分场景。
配置精准的访问日志格式
默认日志格式不包含足够信息来判断“异常”,需自定义 log_format,加入关键字段:
- $status:HTTP 状态码,用于识别 4xx/5xx 请求
- $request_time:请求耗时,识别慢速攻击或资源耗尽行为
- $body_bytes_sent:响应体大小,辅助判断是否返回了大量数据(如扫描探测)
- $http_user_agent 和 $http_referer:辅助识别爬虫、恶意 UA 或非法来源
- $remote_addr 和 $http_x_forwarded_for:确保获取真实客户端 IP(注意代理链处理)
示例配置:
log_format custom '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time $upstream_response_time';access_log /var/log/nginx/access.log custom;
用 map 模块标记可疑请求
利用 Nginx 的 map 指令,根据请求特征动态打标,再写入独立日志,便于后续聚焦分析:
- 对高频 404、403、500 请求的 IP 打上 “abnormal_4xx” 标签
- 对 $request_time > 10 的慢请求标记为 “slow_attack”
- 对空 UA、含 sqlmap/burpsuite/nikto 等关键词的 UA 标记为 “scanner”
示例:
map $status $is_abnormal {~^(4|5)[0-9]{2}$ "1";
}
map $request_time $is_slow {
>10 "1";
}
map $http_user_agent $is_scanner {
~*(sqlmap|burp|nikto|dirb) "1";
}
log_format abnormal '$remote_addr [$time_local] "$request" $status $request_time "$http_user_agent" $is_abnormal $is_slow $is_scanner';
access_log /var/log/nginx/abnormal.log abnormal if=$is_abnormal;
用 logrotate + 脚本做轻量级实时分析
无需引入 ELK 或 Prometheus,用 shell 脚本配合 logrotate 定期提取高频异常 IP:
- 每小时执行一次:
awk '{print $1}' /var/log/nginx/abnormal.log | sort | uniq -c | sort -nr | head -20 - 过滤出 5 分钟内出现 >50 次 403 的 IP,可直接加入 deny 规则或通知运维
- 配合
fail2ban:将异常日志路径加入 fail2ban 的 filter,自动封禁 IP(推荐用于生产环境)
注意代理环境下的 IP 真实性
如果前端有 CDN、负载均衡或反向代理,$remote_addr 是上游地址,不是真实用户 IP:
- 确保 Nginx 开启 set_real_ip_from 并配置可信代理网段
- 使用 $realip_remote_addr 替代 $remote_addr(需加载 realip 模块)
- 检查 X-Forwarded-For 头是否被伪造,建议只信任最后一跳可信代理传入的值


















