Nginx 限流限速配置教程:防 CC 攻击、保护后端,limit_req 与 limit_conn 实战


网站被人恶意刷请求、某个接口被脚本疯狂调用、下载文件被人抢带宽——这些场景都需要 Nginx 限流限速来保护服务器。Nginx 是几乎所有网站最前面的一层,它自带的限流功能既高效又零成本:limit_req 限请求速率、limit_conn 限并发连接、limit_rate 限下载速度。这篇文章把 Nginx 限流限速的核心配置讲透,照着配就能让你的网站扛住恶意流量。

一、为什么需要 Nginx 限流

服务器资源是有限的,而恶意或异常的流量是无限的:

  • CC 攻击:模拟正常用户大量请求,把 PHP/数据库打挂
  • 接口刷量:登录接口被人无限尝试密码、短信接口被人刷爆
  • 盗链下载:图片、文件被人直接引用,白白消耗带宽
  • 爬虫失控:个别爬虫疯狂抓取,拖慢正常用户访问

在 Nginx 这一层限流,是最靠前、最省资源的防线,能在请求到达后端之前就把流量挡掉。

二、limit_req:限制请求速率(防 CC)

limit_req 基于漏桶算法,限制同一个 IP 每秒/每分钟的请求数。

基本配置:

# 在 http 块定义限流区域
http {
    # 每个 IP 每 1 秒最多 5 个请求,超出部分进 burst 缓冲
    limit_req_zone $binary_remote_addr zone=req_zone:10m rate=5r/s;

    server {
        # 在需要限流的 location 使用
        location / {
            limit_req zone=req_zone burst=10 nodelay;
        }
    }
}

参数说明:

  • rate=5r/s:每个 IP 限速 5 次/秒
  • burst=10:允许瞬时突发 10 个请求(排队缓冲)
  • nodelay:缓冲的请求立即处理,不排队等待
  • limit_req_status 429:超限时返回 429 状态码

登录接口单独限制(更严格,防止爆破):

location /login {
    limit_req_zone $binary_remote_addr zone=login_zone:10m rate=1r/s;
    limit_req zone=login_zone burst=3 nodelay;
}

这样每个 IP 登录接口 1 秒最多 1 次,能有效防止密码暴力破解。

三、limit_conn:限制并发连接

有些攻击不是频率高,而是同时建立大量连接挂起。limit_conn 限制单个 IP 的最大并发连接数。

http {
    # 定义并发连接限制区域
    limit_conn_zone $binary_remote_addr zone=conn_zone:10m;

    server {
        location / {
            limit_conn conn_zone 10;      # 每个 IP 最多 10 个并发连接
        }
    }
}

典型场景:图片服务器、下载服务器限制每个 IP 并发连接,防止被工具多线程拉爆带宽。

四、limit_rate:限制下载速度

limit_rate 限制单个连接的传输速率,用于防止个别用户独占带宽。

server {
    # 限制每个连接下载速度 500KB/s
    limit_rate 500k;

    # 也可以对整个 location 限速
    location /download/ {
        limit_rate 1m;      # 下载目录限制 1MB/s
        limit_rate_after 10m;  # 前 10MB 不限速,之后限速
    }
}

limit_rate_after 很实用:先让用户以正常速度下载前 10MB,之后限速,既照顾体验又防占用带宽。

五、综合实战:一个防止 CC 的推荐配置

http {
    # 请求速率限制
    limit_req_zone $binary_remote_addr zone=req:10m rate=10r/s;
    # 并发连接限制
    limit_conn_zone $binary_remote_addr zone=conn:10m;

    server {
        listen 80;
        server_name example.com;

        location / {
            # 全局限频 + 限制并发
            limit_req zone=req burst=20 nodelay;
            limit_conn conn 10;
            limit_req_status 429;

            proxy_pass http://127.0.0.1:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }

        # 后台管理接口单独严格限流
        location ~ ^/admin/ {
            limit_req zone=req burst=5 nodelay;
            limit_conn conn 3;
            limit_req_status 429;
            proxy_pass http://127.0.0.1:8080;
        }
    }
}

六、常见问题与注意事项

Q1:限流误伤了正常用户怎么办?

把 burst 调大一些,让正常的小流量波动不会触发。也可以对已知的正常爬虫(百度、谷歌)放行。

Q2:怎么放行特定 IP 或屏蔽某些 IP?

# 用 geo 或 map 区分
geo $limit {
    default 1;
    192.168.1.0/24 0;        # 内网不限流
    你的IP 0;                  # 你自己不限流
}

map $limit $limit_key {
    0 "";
    1 $binary_remote_addr;
}

limit_req_zone $limit_key zone=req:10m rate=10r/s;

当 $limit_key 为空时不会限流,这样就实现了"白名单不限流"。

Q3:限流返回 429 后,怎么让用户看到友好页面?

location / {
    limit_req zone=req burst=20 nodelay;
    error_page 429 /too_many.html;
}

location = /too_many.html {
    root /var/www/html;
    internal;
}

Q4:可以按 URL 而不是按 IP 限流吗?

可以,把 zone 的 key 改成 $request_uri 即可,但要注意多个用户会互相影响,更常用的是按 IP。

Q5:限流会影响 SEO 收录吗?

正常设置一般不会。搜索引擎爬虫频率不高,只要 rate 别设太低(别低于 1r/s)基本无影响。真被误限可以放行白名单。

七、验证限流是否生效

配置好后重载 Nginx:

nginx -t          # 检查配置语法
nginx -s reload   # 重载配置

用 ab(ApacheBench)压测验证:

ab -n 1000 -c 50 http://example.com/

# 观察 Nginx 日志中的 429 状态码
tail -f /var/log/nginx/access.log | grep 429

大量 429 说明限流正常生效,成功挡住了超出的请求。

总结

Nginx 限流限速是保护网站的第一道防线:limit_req 挡 CC 高频攻击、limit_conn 限并发连接、limit_rate 控下载带宽,配合白名单和 429 友好页面,一套配好就能让网站从容应对恶意流量。记住核心套路:定义 zone → 在 location 里启用 → 重载生效 → 压测验证。需要更强防护的话,可以再配合本站的 iptables 防火墙教程和 WAF 方案层层加固。


手机扫码阅读

微信或手机浏览器扫一扫,随时随地随心阅读与分享

网站搬家迁移完整教程:WordPress 网站换服务器、换域名,数据无损迁移全流程

MySQL 主从复制配置教程:读写分离、自动备份,数据库零丢失高可用

评 论
更换验证码