Nginx 日志分析如何识别恶意 IP 段并进行封禁?

文章导读
遇到恶意流量时,最稳妥的做法是先通过日志确认攻击特征,再针对单个高频 IP 进行封禁,避免直接封禁整个网段导致误伤正常用户。
📋 目录
  1. A 命令速用版
  2. B Nginx 日志分析原理
  3. C 分步处理
  4. D 获取真实 IP 配置方案
  5. E Fail2ban 基础配置示例
  6. F 怎么验证是否生效
  7. G 常见坑
  8. H 参考来源
A A

遇到恶意流量时,最稳妥的做法是先通过日志确认攻击特征,再针对单个高频 IP 进行封禁,避免直接封禁整个网段导致误伤正常用户。

先说结论:日志分析是定位问题的手段,封禁是后续动作,建议设定具体阈值(如每分钟超过 100 次)后再考虑自动化,防止误封正常流量。

  • 先判断:确认是扫描、爬虫还是正常高峰,避免把 CDN 节点当成攻击者。
  • 优先做:先用 Nginx 自带 deny 指令封禁单个 IP,观察业务影响。
  • 再验证:确认封禁生效后,再考虑是否引入 fail2ban 等自动化工具。

命令速用版

以下命令用于快速提取访问频率最高的 IP 地址,假设日志格式为默认的 combined 格式:

awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -n 10

如果需要查看特定时间段(例如最近 1000 行):

tail -n 1000 /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -nr | head -n 10

按网段聚合分析:若需识别恶意 IP 段,可提取前三段进行统计:

awk '{print $1}' /var/log/nginx/access.log | cut -d. -f1-3 | sort | uniq -c | sort -nr | head -n 10

Nginx 日志分析原理

Nginx 访问日志记录了每个请求的来源 IP、时间、请求路径和状态码。恶意行为通常表现为某个 IP 在短时间内发起大量请求,或者频繁访问不存在的路径(导致 404 激增)。通过统计 IP 出现频率,可以找出异常流量来源。但需要注意,日志中的 IP 不一定是用户真实 IP,如果服务器前有 CDN 或负载均衡器,记录的可能是一层代理的地址。

分步处理

1. 备份配置文件
修改配置前务必备份,防止配置错误导致服务无法启动:

cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak

2. 提取可疑 IP
使用上述命令找出频率最高的 IP。如果某个 IP 的请求量远超其他 IP,且伴随大量 403、404 或 500 状态码,可列为可疑对象。

3. 创建封禁配置文件
不要在主配置文件中直接写大量 deny 规则,建议单独建立一个文件,例如 /etc/nginx/conf.d/deny_ips.conf

Nginx 日志分析如何识别恶意 IP 段并进行封禁?
deny 192.168.1.100;
deny 10.0.0.5;

4. 在主配置中引入
nginx.confhttpserver 块中添加 include 指令。注意:server 块中的规则优先级高于 http 块,且规则按顺序匹配,一旦匹配成功即停止。

http {
    include /etc/nginx/conf.d/deny_ips.conf;
    server {
        # 或者放在 server 块内针对特定域名生效
        include /etc/nginx/conf.d/deny_ips.conf;
    }
}

5. 检查配置并重载
修改配置前务必检查语法,避免写错导致 Nginx 无法启动:

nginx -t
nginx -s reload

获取真实 IP 配置方案

如果站点接了 CDN,日志里的 IP 可能是 CDN 节点的 IP。直接封禁会导致该节点下所有用户无法访问。此时需要配置 Nginx 获取真实 IP(需编译时包含 ngx_http_realip_module):

http {
    set_real_ip_from 10.0.0.0/8; # CDN 厂商提供的 IP 段
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;
}

Fail2ban 基础配置示例

若需自动化封禁,可安装 fail2ban 并配置 /etc/fail2ban/jail.local

[nginx-http-auth]
enabled = true
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 5
bantime = 3600

怎么验证是否生效

1. 本地测试
如果条件允许,用被封禁的 IP 环境发起请求,预期返回 403 Forbidden 状态码。

2. 日志观察
继续观察 access.log,确认被封禁 IP 的请求是否减少,或者状态码是否变为 403。注意,如果攻击者更换 IP 段,封禁单个 IP 可能效果有限。

3. 业务确认
确认正常用户访问不受影响,特别是当你在云服务器上操作时,确保没有误封自己的管理 IP 或办公网出口 IP。

常见坑

  • CDN 导致的误判:如果站点接了 CDN,日志里的 IP 可能是 CDN 节点的 IP。直接封禁会导致该节点下所有用户无法访问。此时需要配置 Nginx 获取真实 IP(如通过 X-Forwarded-For 头)。
  • 封禁网段过大:使用 CIDR 格式(如 192.168.1.0/24)封禁时,务必确认该网段内没有正常用户,否则会造成大面积不可用。
  • 配置优先级:Nginx 的 allow/deny 规则按顺序匹配,一旦匹配成功即停止。确保 allow 规则放在 deny 之前,或者逻辑清晰,避免把自己关在门外。
  • 自动化风险:使用 fail2ban 等工具自动封禁时,要设置合理的阈值和封禁时长,避免因短暂流量波动导致永久封禁。

参考来源

  • Nginx 官方文档:ngx_http_access_module 模块说明,https://nginx.org/en/docs/http/ngx_http_access_module.html
  • Fail2ban 项目仓库:自动化封禁工具参考,https://github.com/fail2ban/fail2ban