网站被恶意刷流量刷接口怎么办:Nginx限速与IP封禁配置思路

    发布时间:2026-09-17 05:00 更新时间:2026-09-17 05:00 阅读量:0

    网站跑着跑着忽然流量飙高、CPU 打满、接口响应变慢,登录后台一看访问日志,某个 IP 或者某几个 IP 在几秒内把同一个接口刷了几百上千次——这是不少站长都会遇到的情况。它未必是漏洞利用,更多是对方用脚本反复请求搜索、下单、发短信、导出这类动态接口,目的可能是抓数据、压测,也可能仅仅是刷着玩。这篇文章讲的是怎么在自己服务器上做合理的限速与封禁:既不写攻击手法,也不教你绕规则,只讲如何让正常用户不受影响地挡住异常请求。

    先分清楚:是被刷流量,还是被刷接口

    流量和接口是两回事。流量型通常表现为带宽跑满、CDN 流量曲线陡增,请求集中在图片、视频、下载这类静态资源上,常见于盗链或被人拿去做压测目标;接口型则是请求数量不大但单次请求消耗资源多,比如搜索、列表分页、登录、短信验证码,这类最容易把数据库和 PHP-FPM 拖垮。排查时先看访问日志的请求分布,用 goaccess 或简单的 awk 统计都能快速定位,比如按 IP 统计一分钟内的请求次数:

    awk '{print $1}' /www/wwwlogs/example.com.log | sort | uniq -c | sort -rn | head -20

    如果某个 IP 的次数远高于正常水平,再去看它请求的 URL 和状态码。这一步很关键:先确认真实来源,再动手限速。如果站点前面挂了 CDN,日志里看到的可能是 CDN 回源 IP 而不是访客真实 IP,这时候要先按前面讲过的回源配置思路拿到真实 IP,否则封禁封的是 CDN 节点,会误伤一大批正常用户。

    Nginx limit_req 限速的配置要点

    Nginx 自带的 ngx_http_limit_req_module 模块是处理高频请求的第一道工具,它基于漏桶算法:请求先进入桶里,桶以固定速率漏水(放行),桶满了就拒绝。它有两个层面,一个是定义共享内存区域,一个是具体 location 里引用。最基础的写法如下,放在 http 块里:

    limit_req_zone $binary_remote_addr zone=req_per_ip:10m rate=10r/s;
    limit_req_status 429;

    这里的 $binary_remote_addr 比 $remote_addr 更省内存,10m 大约能存十几万个 IP 状态(具体数量随 Nginx 版本和键长度变化,以官方文档为准)。rate=10r/s 表示每个 IP 平均每秒放行 10 个请求。然后在需要保护的 location 里引用:

    location /api/ {
        limit_req zone=req_per_ip burst=20 nodelay;
        proxy_pass http://127.0.0.1:8080;
    }

    burst 是允许的突发数量,nodelay 表示突发部分立即放行而不排队延迟。这两个参数决定了限速的“手感”:

    不写 nodelay 时,超出的请求会被延迟处理,队列满了才返回 503(或你设置的 limit_req_status)。这种模式对爬虫友好但对正常用户也可能造成等待;写了 nodelay,突发请求直接放行,超过 burst 的立刻拒绝,更适合接口防刷。实际设置要结合业务:登录、短信类接口可以压到 rate=2r/s、burst=5;普通页面接口可以放到 rate=20r/s、burst=50。数值没有标准答案,建议先在测试环境观察正常用户的请求节奏再定。

    还有几个容易踩的坑:一是 limit_req_zone 必须定义在 http 块,不能写在 server 里,否则 Nginx 启动会报错;二是限速只作用于 Nginx 能看到的连接,如果攻击流量已经打满带宽,限速救不了,得靠上层清洗或 CDN;三是 429 状态码要记得在站点里做友好提示,别让正常用户看到一片空白。

    IP 封禁、白名单与验证闭环

    限速解决的是“频率”,但有些 IP 是固定几个、持续不断刷,这时候直接封禁更干脆。Nginx 层可以用 deny 指令,也可以配合 ngx_http_geo_module 或 map 做批量管理。简单写法:

    location /api/ {
        deny 203.0.113.10;
        allow 198.51.100.0/24;
        deny all;
        limit_req zone=req_per_ip burst=20 nodelay;
        proxy_pass http://127.0.0.1:8080;
    }

    注意 deny/allow 是按顺序匹配的,写错顺序会导致规则失效,白名单一定要放在 deny all 前面。如果恶意 IP 很多,手动改配置不现实,可以用 map 配合一个外部文件,或者用 iptables/firewalld 在系统层做临时封禁,但系统层封禁要小心别把自己的管理 IP 也封进去,操作前先确认当前 SSH 来源。

    封禁之后一定要做验证闭环:过半小时再看一次日志,确认目标 IP 的请求是否真的被挡住、有没有误伤正常用户。同时给关键接口加上日志标记,方便以后回溯。如果发现封禁后请求换了一批 IP 继续来,说明对方在用代理池,这时候单纯封 IP 意义有限,应该把重点转回 limit_req 限速 + 业务层验证码/令牌校验,从“认 IP”变成“认行为”。

    最后提醒一句:限速和封禁都是缓解手段,不是根治方案。真正要稳,还是得让接口本身有成本——登录加验证码、短信接口做频率与手机号双重限制、导出类接口做权限与次数控制。把这些基础做扎实,再配合 Nginx 的限速兜底,网站面对刷流量时就不会手忙脚乱。配置改完记得 nginx -t 检查语法再 reload,具体参数以你的 Nginx 版本和官方文档为准。

    继续阅读

    📑 📅
    宝塔面板网站防跨站攻击open_basedir怎么配:报错原因、目录放行与多站隔离实践 2026-09-17
    服务器时间不对导致HTTPS报错与定时任务错乱:ntp/chrony校时与宝塔同步配置实操 2026-09-16
    域名解析生效慢与解析被劫持:TTL、DNSSEC与本地缓存排查 2026-09-16
    WordPress多站点网络搭建:子域名与子目录怎么选、域名映射与迁移注意点 2026-09-16
    Nginx与PHP-FPM超时怎么配:三处超时参数的关系与取舍 2026-09-16
    WordPress图片站提速:WebP批量转换、懒加载与Nginx静态直返 2026-09-17
    同一台服务器跑多个网站:Nginx server_name 匹配顺序与默认站点防串站配置 2026-09-17
    Nginx gzip 与 Brotli 压缩怎么开:级别、预压缩与不生效排查 2026-09-17
    宝塔面板 Nginx 与 Apache 该选哪个:并发模型差异与切换后伪静态失效处理 2026-09-17
    网站图片被外站盗链怎么办:Nginx防盗链配置与误伤排查 2026-09-17