Nginx 限流防刷完全指南从原理到生产实战指南

 更新时间:2026年05月06日 10:11:09   作者:0xDevNull  
本文给大家介绍Nginx限流防刷完全指南从原理到生产实战指南,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧

一、核心原理

Nginx 提供两个核心模块实现限流,各司其职:

模块功能算法/机制适用场景
ngx_http_limit_req_module限制单个 IP 在单位时间内的请求数量漏桶算法防刷接口、控制 QPS
ngx_http_limit_conn_module限制单个 IP 同时建立的连接数量连接计数防 CC 攻击、防连接耗尽

漏桶算法:以固定速率处理请求,超出速率的请求排队或被拒绝。burst 定义桶容量,nodelay 决定是否延迟处理。

二、环境准备

系统要求:Ubuntu 20.04 / CentOS 7+,Nginx ≥ 1.1.8(当前稳定版均支持)。

# Ubuntu
sudo apt update && sudo apt install nginx -y
# CentOS
sudo yum install epel-release -y && sudo yum install nginx -y

确认模块已编译

nginx -V 2>&1 | grep -o with-http_limit_req_module
nginx -V 2>&1 | grep -o with-http_limit_conn_module

三、基础配置:限制单 IP 请求速率

3.1 定义限流区域(http 块)

http {
    # 按客户端IP限流,10MB共享内存(约存16万IP),每秒10个请求
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
    # 登录接口专用:更严格的限制
    limit_req_zone $binary_remote_addr zone=login_limit:5m rate=2r/s;
    # 并发连接限制
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
}

为什么用 $binary_remote_addr 而非 $remote_addr? 二进制格式更省内存,推荐生产环境使用。

3.2 应用限流规则(server/location 块)

server {
    listen 80;
    server_name api.example.com;
    location /api/ {
        # 应用限流:允许突发20个请求,nodelay立即处理突发,超出部分直接拒绝
        limit_req zone=api_limit burst=20 nodelay;
        # 自定义限流返回状态码(429比默认503更符合语义)
        limit_req_status 429;
        proxy_pass http://backend_server;
    }
    location /api/login {
        # 登录接口使用更严格的限流
        limit_req zone=login_limit burst=5 nodelay;
        limit_req_status 429;
        proxy_pass http://auth_service;
    }
}

参数深度解析

  • rate=10r/s:这是长期的平均速率,也可写 30r/m(每分钟30次)
  • burst=20:当请求瞬间超过 10r/s 时,多出来的请求会先进入“突发桶”排队。
  • nodelay:加上这个参数,突发桶里的 20 个请求会立即被处理,而不是按每秒 10 个的速度排队。如果不加 nodelay,请求会被延迟处理,适合对实时性要求不高的场景。

四、组合防护:速率 + 连接双限制

生产环境推荐同时启用双重保护:

http {
    # 速率限制区
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=50r/s;
    # 连接数限制区
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
    server {
        location /api/ {
            proxy_pass http://backend_server;
            # 速率限制:每秒50个,允许突发100个
            limit_req zone=api_limit burst=100 nodelay;
            # 连接数限制:单个IP最多同时保持50个连接
            limit_conn conn_limit 50;
            limit_conn_status 429;
        }
    }
}

五、精细化限流策略

5.1 按接口路径限流(防扫描)

防止扫描器遍历 API,对每个 URI 单独计数:

http {
    # $uri 不包含查询参数,如需区分参数用 $request_uri
    limit_req_zone $uri zone=per_uri:10m rate=10r/s;
}
server {
    location / {
        limit_req zone=per_uri burst=20 nodelay;
        limit_req_status 429;
        proxy_pass http://backend;
    }
}

5.2 动态分级限流(VIP用户)

通过 map 实现不同用户等级的差异化限流:

http {
    # 从请求头获取用户等级(需后端传递)
    map $http_x_user_level $rate_limit {
        "vip"     "100r/s";
        "normal"  "10r/s";
        default   "2r/s";
    }
    limit_req_zone $binary_remote_addr zone=dynamic:10m rate=$rate_limit;
    server {
        location /api/ {
            limit_req zone=dynamic burst=5 nodelay;
            proxy_pass http://backend;
        }
    }
}

注:rate 使用变量需 Nginx 1.15.10+。

5.3 下载限速 + 并发限制

location /download/ {
    limit_conn conn_limit 2;      # 单IP最多2个并发下载
    limit_rate 500k;              # 单连接限速500KB/s
    alias /data/files/;
}

5.4针对敏感接口

登录和验证码接口是暴力破解的重灾区,需要设置更严格的规则:

http {
    # 专门为登录接口定义一个更严格的限流区:每秒仅允许 2 次请求
    limit_req_zone $binary_remote_addr zone=login_limit:5m rate=2r/s;
    server {
        # 普通接口
        location /api/ {
            limit_req zone=api_limit burst=50 nodelay;
            proxy_pass http://backend_server;
        }
        # 登录接口(单独配置)
        location /api/login {
            limit_req zone=login_limit burst=5 nodelay;
            limit_req_status 429;
            proxy_pass http://backend_server;
        }
    }
}

六、白名单与动态控制

6.1 白名单配置(geo + map 技巧)

Nginx 的 limit_req 不能直接通过 if 开关,需用 zone 切换实现"跳过限制":

http {
    # 定义白名单
    geo $whitelist {
        default 0;
        203.0.113.0/24 1;    # 公司出口IP段
        192.168.1.100 1;
    }
    # 正常限流区
    limit_req_zone $binary_remote_addr zone=global:10m rate=20r/s;
    # 虚拟高速区(白名单IP使用,实际不限流)
    limit_req_zone $binary_remote_addr zone=dummy:1m rate=10000r/s;
    # 根据白名单动态选择zone
    map $whitelist $limit_zone {
        1 "dummy";
        0 "global";
    }
    # 登录专用区
    limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
    map $whitelist $login_zone {
        1 "dummy";
        0 "login";
    }
    # 并发限制
    limit_conn_zone $binary_remote_addr zone=connip:10m;
    # 日志格式增加限流信息
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" limit_req_status=$limit_req_status';
    server {
        listen 80;
        server_name api.example.com;
        access_log /var/log/nginx/api_access.log main;
        limit_req_status 429;
        limit_conn_status 429;
        # 全局接口
        location / {
            limit_req zone=$limit_zone burst=30 nodelay;
            limit_conn connip 20;
            proxy_pass http://backend;
        }
        # 登录接口
        location /api/login {
            limit_req zone=$login_zone burst=3 nodelay;
            proxy_pass http://auth;
        }
        # 下载接口
        location /download/ {
            limit_conn connip 2;
            limit_rate 500k;
            alias /data/downloads/;
        }
    }
}

七、CDN / 反向代理场景

如果 Nginx 前有 CDN 或 NAT,需获取真实客户端 IP:

# 配置真实IP来源
set_real_ip_from 10.0.0.0/8;      # CDN节点网段
set_real_ip_from 172.16.0.0/12;
real_ip_header X-Forwarded-For;
# 使用真实IP限流
limit_req_zone $http_x_forwarded_for zone=cdn_limit:10m rate=20r/s;

八、友好的限流提示

自定义 429 错误页面,返回 JSON:

server {
    # 自定义限流错误
    error_page 429 = @rate_limited;
    location @rate_limited {
        default_type application/json;
        return 429 '{"code": 429, "msg": "请求过于频繁,请稍后再试"}';
    }
    location /api/ {
        limit_req zone=api_limit burst=20 nodelay;
        limit_req_status 429;
        proxy_pass http://backend;
    }
}

九、测试与验证

9.1 ApacheBench (ab)

# 安装
sudo apt install apache2-utils   # Ubuntu
sudo yum install httpd-tools      # CentOS
# 发送100个请求,并发10个
ab -n 100 -c 10 http://api.example.com/api/test

9.2 curl 循环测试

for i in {1..100}; do
    http_code=$(curl -s -o /dev/null -w "%{http_code}" http://api.example.com/api/test)
    echo "Request $i: $http_code"
done

9.3 日志排查

# 实时查看限流日志
tail -f /var/log/nginx/error.log | grep "limiting requests"
# 统计429状态码数量
grep " 429 " /var/log/nginx/access.log | wc -l
# 查看限流状态(若配置了日志格式)
tail -f /var/log/nginx/api_access.log

十、进阶优化

10.1 调整日志级别

limit_req_log_level error;    # 默认warn,可选info/notice/warn/error
limit_conn_log_level error;

10.2 结合 Fail2ban 自动封禁

配置 Fail2ban 监控 429 日志,超限直接 iptables 封禁:

# /etc/fail2ban/jail.local
[nginx-req-limit]
enabled  = true
filter   = nginx-req-limit
action   = iptables-multiport[name=ReqLimit, port="http,https"]
logpath  = /var/log/nginx/api_access.log
maxretry = 10
findtime = 60
bantime  = 600
# /etc/fail2ban/filter.d/nginx-req-limit.conf
[Definition]
failregex = ^<HOST> -.* 429
ignoreregex =

10.3 平滑重载配置

sudo nginx -t && sudo systemctl reload nginx

十一、完整生产配置示例

http {
    # ========== Zone 定义 ==========
    limit_req_zone $binary_remote_addr zone=global:20m rate=20r/s;
    limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
    limit_req_zone $binary_remote_addr zone=dummy:1m rate=10000r/s;
    limit_conn_zone $binary_remote_addr zone=connip:10m;
    # ========== 白名单 ==========
    geo $whitelist {
        default 0;
        203.0.113.0/24 1;
    }
    map $whitelist $limit_zone {
        1 "dummy";
        0 "global";
    }
    map $whitelist $login_zone {
        1 "dummy";
        0 "login";
    }
    # ========== 日志 ==========
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" limit_req_status=$limit_req_status';
    server {
        listen 80;
        server_name api.example.com;
        access_log /var/log/nginx/api_access.log main;
        limit_req_status 429;
        limit_conn_status 429;
        # 全局API
        location /api/ {
            limit_req zone=$limit_zone burst=30 nodelay;
            limit_conn connip 20;
            proxy_pass http://backend;
        }
        # 登录(更严格)
        location /api/login {
            limit_req zone=$login_zone burst=3 nodelay;
            proxy_pass http://auth;
        }
        # 下载
        location /download/ {
            limit_conn connip 2;
            limit_rate 500k;
            alias /data/downloads/;
        }
        # 限流提示
        error_page 429 = @rate_limited;
        location @rate_limited {
            default_type application/json;
            return 429 '{"code":429,"msg":"请求过于频繁,请稍后再试"}';
        }
    }
}

十二、关键注意事项

要点说明
共享内存大小10MB 约存16万IP,日活大需调大
burst + nodelay不加 nodelay 会延迟排队,加则直接丢弃超限请求
CDN/代理必须配置 real_ip_header 获取真实IP,否则误伤
阈值调优根据后端实际抗压能力和正常用户习惯动态调整
限流非目的本质是为后端争取恢复空间,需配合监控和自动封禁

通过合理组合 limit_reqlimit_conn,配合白名单、分级限流、友好提示和 Fail2ban 联动,可以为 API 构建一道低成本、高效率的防护墙。

到此这篇关于Nginx 限流防刷完全指南从原理到生产实战指南的文章就介绍到这了,更多相关nginx 限流防刷内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • nginx中一个请求的count计数跟踪浅析

    nginx中一个请求的count计数跟踪浅析

    这篇文章主要给大家介绍了关于nginx中一个请求的count计数跟踪的相关资料,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-01-01
  • Nginx服务器配置https安全协议的实现

    Nginx服务器配置https安全协议的实现

    HTTP是互联网中最常用的协议,用于从服务器传输超文本到浏览器,HTTPS是HTTP的安全版本,本文就来介绍一下Nginx服务器配置https安全协议的实现,感兴趣的可以了解一下
    2024-09-09
  • nginx rewrite 伪静态配置参数和使用例子

    nginx rewrite 伪静态配置参数和使用例子

    nginx下伪静态配置参数详细说明,使用nginx的朋友,nginx rewrite 伪静态配置参数和使用例子 附正则使用说明
    2010-07-07
  • Nginx实现动态路由映射的完整示例

    Nginx实现动态路由映射的完整示例

    在Nginx中实现动态路径映射,通常使用正则表达式location+捕获组+ alias或root来完成,下面给大家介绍Nginx实现动态路由映射的完整示例,感兴趣的朋友跟随小编一起看看吧
    2026-02-02
  • Nginx could not build the server_names_hash 错误的解决办法

    Nginx could not build the server_names_hash 错误的解决办法

    这篇文章主要介绍了Nginx could not build the server_names_hash 错误的解决办法,需要的朋友可以参考下
    2014-03-03
  • 利用nginx如何匹配多个条件

    利用nginx如何匹配多个条件

    这篇文章主要给大家介绍了利用nginx如何匹配多个条件的相关资料,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-06-06
  • 国内一些常用PHP的CMS的Nginx服务器的伪静态规则整理

    国内一些常用PHP的CMS的Nginx服务器的伪静态规则整理

    当我们从apache服务器转向Nginx服务器的时候,它们的伪静态规则就不一样了,所以你熟悉Nginx服务器的伪静态规则,自己写当然也好
    2011-03-03
  • Nginx中修复安全配置漏洞的实战指南

    Nginx中修复安全配置漏洞的实战指南

    这篇文章主要为大家详细介绍了Nginx中修复安全配置漏洞的实战指南,文中介绍了如何识别常见的漏洞并进行修复,大家可以根据需要进行选择
    2025-09-09
  • nginx出现500 Internal Server Error错误的解决方法

    nginx出现500 Internal Server Error错误的解决方法

    这篇文章主要介绍了nginx出现500 Internal Server Error错误的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或工作有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-09-09
  • nginx代理前端请求的实现示例

    nginx代理前端请求的实现示例

    本文介绍了在Vue3项目中使用Axios调用后端接口,并通过Nginx进行反向代理以解决跨域问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-01-01

最新评论