帮助中心 >  技术知识库 >  云服务器 >  服务器教程 >  Nginx 日志量暴涨时,如何用 map + geo 精准屏蔽恶意流量

Nginx 日志量暴涨时,如何用 map + geo 精准屏蔽恶意流量

2026-05-14 16:38:38 705

Nginx 日志量暴涨时,如何用 map + geo 精准屏蔽恶意流量

线上业务最怕两件事: 一种是被扫目录,另一种是日志爆炸。

很多服务器并不是 CPU 或带宽先扛不住,而是 /var/log/nginx/access.log 先被刷到几十 GB,磁盘 IO 飙升,最终影响正常业务。

传统做法通常是:

if ($http_user_agent ~* "curl|python") {

    return 403;

}

或者:

deny 1.1.1.1;

问题在于:

· if 滥用容易产生副作用

· IP 黑名单维护困难

· 大量 location 判断性能差

· 无法灵活组合条件

生产环境更推荐使用:

· geo

· map

· 条件日志

· 限流联动

组合实现精准拦截。




典型攻击日志

先看一类常见扫描:

GET /.env

GET /wp-admin

GET /vendor/phpunit

GET /boaform/admin/formLogin

特点:

· 高频

· UA 混乱

· 来源 IP 分散

· 目标路径固定

如果直接全部记录日志:

access.log

磁盘很快被刷满。




使用 geo 标记恶意 IP

编辑 nginx 配置:

geo $bad_ip {

    default 0;

 

    45.134.26.0/24 1;

    192.168.1.100 1;

}

说明:

· 0 表示正常

· 1 表示恶意

这里比 deny 更灵活。

因为:

if ($bad_ip) {

    return 403;

}

只是其中一种玩法。

你还可以:

· 不记录日志

· 单独记录

· 限速

· 转发风控系统




使用 map 标记恶意请求路径

继续增加:

map $request_uri $bad_uri {

    default 0;

 

    ~*\\.env 1;

    ~*wp-admin 1;

    ~*phpunit 1;

    ~*boaform 1;

}

这里使用正则匹配危险路径。

相比 location:

location ~* \\.env {

}

map 性能更高。

因为它发生在请求处理前期。




组合条件判断

现在可以组合:

map "$bad_ip$bad_uri" $block_request {

    default 0;

 

    "11" 1;

    "01" 1;

}

含义:

bad_ip

bad_uri

是否封禁

1

1

封禁

0

1

封禁

1

0

放行

即:

· 只要访问危险 URI

· 或危险 IP

直接封禁。




实际拦截配置

server 中:

server {

 

    listen 80;

    server_name test.com;

 

    if ($block_request) {

        return 403;

    }

 

    location / {

        proxy_pass http://www.landui.com;

    }

}

效果非常直接。




更高级玩法:危险请求不写日志

很多时候:

真正拖垮机器的不是请求。

而是日志。

配置:

map $block_request $loggable {

    default 1;

    1 0;

}

然后:

access_log /var/log/nginx/access.log main if=$loggable;

效果:

· 正常请求记录

· 恶意请求不写日志

日志量会瞬间下降。




配合 limit_req 防 CC

继续增加:

limit_req_zone $binary_remote_addr zone=req_limit:10m rate=5r/s;

location:

location / {

 

    limit_req zone=req_limit burst=20 nodelay;

 

    proxy_pass http://www.landui.com;

}

说明:

· IP 每秒 5 请求

· 突发允许 20

· 超出直接限制

配合前面的恶意 URI 判断,效果非常好。




查看哪些 URI 被扫最多

推荐直接分析:

awk '{print $7}' access.log | sort | uniq -c | sort -nr | head

输出类似:

15231 /.env

12011 /wp-login.php

9831 /vendor/phpunit

这样可以持续更新:

map

规则库。




最终建议

生产环境不要依赖:

if + deny

硬拦截。

更推荐:

· geo 标记 IP

· map 标记行为

· 条件日志

· limit_req 限流

· fail2ban 联动

核心思想是:

“不要让恶意请求消耗日志、IO、CPU。”

这比单纯 403 更重要。

 


提交成功!非常感谢您的反馈,我们会继续努力做到更好!

这条文档是否有帮助解决问题?

非常抱歉未能帮助到您。为了给您提供更好的服务,我们很需要您进一步的反馈信息:

在文档使用中是否遇到以下问题: