mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
2229 字
6 分钟
2026年05月08日 | Nginx 限流与防爬虫的实战配置
2026-05-08

Nginx 限流与防爬虫的实战配置#

用户要我扮演"媚娘"这个角色,她是一个"皇上的毒舌妖姬",要写一篇技术教程文章,主题是"Nginx 限流与防爬虫的实战配置"。

关键要求:

  1. 保持媚娘人设:嘴毒、会吐槽、俏皮、鲜活、带点阴阳怪气,但骨子里在帮人
  2. 文风要像真人在说话,不能写成官方说明、AI公文、客服腔、模板腔
  3. 可以损读者两句、吐槽常见蠢操作,但不能空洞骂街
  4. 文章要有明显的个人风格和情绪
  5. 不要出现塑料句如”随着时代发展""总而言之""希望对你有帮助”
  6. 不要自称AI
  7. 1000-1600字
  8. 直接输出正文,不要标题、Frontmatter等

结构要求:

  • 开头要抓人
  • 中间4-8个小节
  • 结尾要像媚娘收尾

内容重点:

  • 技术教程:重点写实操、踩坑、避坑
  • Nginx限流与防爬虫实战配置

我需要写得像一个真实的、有个性的人在说话,带着调侃和毒舌,但同时真的在教技术。

让我构思一下结构:

  1. 开头 - 抓人,带入媚娘人设,吐槽一下为什么要限流防爬虫

  2. 限流基础配置 - ngx_http_limit_req_module的实用技巧和常见错误

  3. 限流进阶 - 连接数和带宽控制的高级配置

  4. 防爬虫 - 基于User-Agent和请求特征的识别策略

  5. 防爬虫进阶 - 验证码、行为分析等更智能的防护措施

  6. 实用配置示例 - 提供可直接使用的完整配置片段

  7. 常见问题与解决方案 - 总结技术要点和最佳实践

现在开始写作,注意保持毒舌但务实的风格。

哟,又来了一个被爬虫爬得死去活来的小可怜?

本宫今天心情好,来教你们怎么用 Nginx 把那些不要脸的爬虫和 DDOS 崽们收拾得服服帖帖。别急,先把你们那些“服务器又被打挂了”“接口被人刷爆了”的破事儿放一放,看看本宫是怎么玩转限流和防爬虫的。

先说好,nginx 这个东西吧,配置起来其实不难,难的是你们这些人不看文档瞎配。limit_req、limit_conn、map 这些玩意儿,你们真的用过吗?还是只会 Ctrl+C/V 别人的配置然后问为什么不管用?

一、先把限流配了,别等被人打死了才想起来#

你们知道什么叫 limit_req 吗?就是限制请求速率的。本宫见过太多人压根不知道这玩意儿,或者配了等于没配。

简单粗暴版:

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server {
location /api/ {
limit_req zone=mylimit burst=20 nodelay;
proxy_pass http://backend;
}
}

这段啥意思呢?$binary_remote_addr 是按 IP 来限制,10m 的共享内存能存大概 16 万个 IP,rate=10r/s 意思是每秒最多 10 个请求。burst=20 则是突发容量,nodelay 是不等待直接处理。

但本宫要骂人了——你们配 limit_req 的时候,有没有先在 http 块定义 limit_req_zone?这玩意儿放 server 里是不好使的!本宫见过七八个把 zone 定义写在 location 里的憨批,配了半天发现根本没用,跑来问本宫怎么回事。你说你配了个寂寞吗?

还有,burst 不是越大越好。你要是配个 burst=1000,那跟没限流有什么区别?一般 burst 设置成 rate 的 2-3 倍就够了,别贪。

二、连接数限制——专治那些开了一堆连接的爬虫#

有些爬虫不按请求速率来,它是一次性给你开几十上百个连接,你用 limit_req 根本管不住它。这个时候就得用 limit_conn:

limit_conn_zone $binary_remote_addr zone=connlimit:10m;
server {
location / {
limit_conn connlimit 10;
proxy_pass http://backend;
}
}

这回懂了吧?一个人只能同时建立 10 个连接,超出的直接给你踹回去。

但这儿有个坑——limit_conn 的计数是按连接建立的时候来的,不是按请求。如果你的上游服务处理很快,连接会快速释放,那实际上能处理的请求可能比你想的多得多。反过来,如果后端响应慢得要死,一个连接占用好几秒,那这个限制就会误伤正常用户。

所以别傻乎乎配个 5 就完事了,先看看你后端响应时间大概是多少,再决定连接数设多少。本宫建议你们打开 nginx 的 stub_status 页面,没事多看看连接数和请求数,心里有个数。

三、防爬虫第一招:User-Agent 你都不看?#

User-Agent 筛选是最基础的,但不是你们想的那么简单。很多人就知道 ban 掉某些关键词,naive!

本宫教你们用 map 做智能判断:

map $http_user_agent $bad_ua {
default 0;
~*curl|wget|scrapy|python-requests|java/ 1;
~*apache-httpclient|go-http-client|axios 1;
~*^Mozilla/4\.0$ 1;
}

然后在 server 或 location 里直接拦:

if ($bad_ua) {
return 403;
}

看到没?正则匹配、大小写不敏感、关键词覆盖,比你们只会写 if ($http_user_agent ~ "curl") 高级到哪里去了。而且 map 是在变量层面做判断,不走 if 逻辑,性能好得多。

但本宫要说了,别以为识别了 User-Agent 就万事大吉。那些稍微有点脑子的爬虫都会伪装成 Chrome、Firefox,你 ban 了一个它换十个。真要防得住,还得往下看。

四、请求特征拦截——Referer 和 URL 参数的骚操作#

Referer 这玩意儿,正常的浏览器访问都会有,但很多爬虫压根不带或者带个乱七八糟的值。可以用这个套路:

valid_referers none blocked server_names ~.google. ~.baidu. ~.bing.;
if ($invalid_referer) {
return 403;
}

none 表示空 Referer,blocked 表示被防火墙删掉的,server_names 放你自己的域名,其他搜索引擎的 Referer 也要放进去,免得 SEO 流量都给你干没了。

还有人喜欢在 URL 里塞签名参数来防爬——比如 /api/data?token=xxx&ts=xxx&sign=xxx。这种本宫就不细说了,各家有各家的玩法。但本宫见过有人把 sign 校验写在 nginx 里,用 lua 或者 njs 做,你猜怎么着?根本拦不住懂行的。该在后端校验的还是得后端校验,nginx 只是第一道门槛,别指望它能包揽所有脏活累活。

五、频率限制 + 人机验证联动——本宫的杀手锏#

前面说的都是被动防守,但有些爬虫它模拟得很像正常用户,你光靠限流根本分不出来。本宫教你们一招狠的——基于 IP 维度的频率拦截 + 触发阈值后返回验证码页面:

geo $limited {
default 0;
include geo.conf;
}
map $limited $limit_403 {
1 $binary_remote_addr;
0 "";
}
limit_req_zone $limit_403 zone=iplimit:10m rate=5r/s;
server {
location / {
limit_req zone=iplimit burst=10;
error_page 495 = @captcha;
}
location @captcha {
return 200 '<html><body><h1>你是不是机器人?</h1><form action="/verify"><input type="submit" value="我确定我不是机器人"></form></body></html>';
add_header Content-Type text/html;
}
}

这段代码的意思是:如果某个 IP 请求过于频繁,先把 limit_req zone 里的计数耗尽,然后 error_page 495 会把它导到验证码页面。真正的浏览器用户点一下按钮就能过,但那些爬虫脚本?哼哼,等着吧。

当然这只是示意,生产环境你们得接真正的验证码服务。但思路就是这个思路:先用 nginx 做频率拦截,触发阈值后再上人机验证,双层保险。

六、限流误伤怎么破?——你们的 IP 被ban错了吗?#

每次讲限流都有人跳出来说:“媚娘!我把正常用户 ban 了怎么办!”

能怎么办?凉拌啊,谁让你配置不看场景的。

首先,别用 binaryremoteaddr单独作为限流key,这玩意儿只区分IP,但现在大公司内网、NAT出口一大堆人共用一个IP,你把整个IP段封了,那一堆人全完蛋。本宫建议用binary_remote_addr 单独作为限流 key,这玩意儿只区分 IP,但现在大公司内网、NAT 出口一大堆人共用一个 IP,你把整个 IP 段封了,那一堆人全完蛋。本宫建议用 `binary_remote_addrhttpuseragent或者http_user_agent` 或者 `binary_remote_addr$cookie.xxx` 来区分,这样就算是同一个 IP,不同浏览器、不同登录状态会被区别对待。

其次,burst 和 nodelay 的组合要慎用。burst=20 nodelay 的意思是允许突发 20 个请求并且不排队等待。如果你的后端比较慢,这 20 个请求会瞬间打过去,反而更容易把服务打挂。本宫建议改成 burst=20(不带 nodelay),这样超出的请求会排队等,起到削峰作用。

最后,白名单机制要有。搞个 IP 段文件,用 geo 模块加载,高级 IP 直接 bypass 限流:

geo $white_ip {
default 0;
10.0.0.0/8 1;
127.0.0.1 1;
1.2.3.4 1;
}
map $white_ip $limit_key {
0 $binary_remote_addr;
1 "";
}
limit_req_zone $limit_key zone=req_limit:10m rate=5r/s;

这样内网 IP 和你自己机器就不会被误伤了。

行了,本宫今天把压箱底的东西都掏给你们了。Nginx 限流防爬虫这事儿,说难听点就是跟爬虫攻城狮斗智斗勇的过程。你们配完别忘了用 ab 或者 wrk 压一压测一测,看看实际效果。另外,限流日志记得开:

limit_req_log_level warn;
limit_conn_log_level warn;

有事没事翻一翻,看看是哪些 IP 在搞事情,然后针对性地调整规则。

好了,滚去干活吧,别让本宫白讲这么多。

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

2026年05月08日 | Nginx 限流与防爬虫的实战配置
https://www.yunio.cn/posts/2026-05-08-nginx-限流与防爬虫的实战配置/
作者
媚娘
发布于
2026-05-08
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录