免费流量被爬虫刷爆:用 Nginx 444 精准拦截(附安全配置清单)

admin admin
2026-10-22 发布 | 2802 字 | 预计 8 分钟 | 2 次阅读 | 0 条评论

云服务器运维实战系列 · 第 7 篇(共 7 篇)

免费流量被爬虫刷爆:用 Nginx 444 精准拦截(附安全配置清单)

免费套餐的服务器,出站流量有额度,超了可能收费。我在面板上看到上行一直有流量、速度还不低,站点没几个人访问,数据却一直在往外发。查了 Nginx 日志,发现是大量 AI 训练爬虫和扫描器在反复抓页面、扫路径。

这篇讲怎么确认是谁在刷、怎么用 Nginx 的 444 状态码在连接层直接掐掉,以及顺手整理的一份安全配置。

第一步:确认流量是谁产生的

先看访问日志里都有哪些 User-Agent、哪些 IP 最活跃:

从访问日志统计活跃 IP 和 User-Agent。
从访问日志统计活跃 IP 和 User-Agent。
Bash
Bash
# 统计访问最多的 IP
sudo awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head

# 统计出现最多的 User-Agent
sudo awk -F'"' '{print $6}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

我看到大量请求来自这些公开的 AI/采集爬虫和扫描器(UA 里直接带名字):

Text
Text
SemrushBot
meta-externalagent / meta-externalfetcher
ClaudeBot / anthropic
Bytespider
python-requests / Go-http-client / curl(扫描器常用)

它们有的反复抓整站,有的专扫 .env、wp-login、phpmyadmin 这类敏感路径。页面虽然小,但架不住请求量大,累计出站流量很可观。

第二步:为什么用 444,而不是 403

Nginx 有个非标准状态码 444(return 444):它不返回任何 HTTP 响应,直接在 Nginx 这一端关闭连接。

命中规则后直接断开连接,不返回响应体。
命中规则后直接断开连接,不返回响应体。

对比:

  • 403 Forbidden:仍然要走完响应,返回一个错误页,客户端还会继续换路径试;
  • 444:连接直接断,不发响应体,不产生出站流量,对刷量的爬虫最省事。

第三步:按 User-Agent 拦截

在 http 块(通常放 /etc/nginx/conf.d/ 下的独立文件,或 nginx.conf 的 http 段)用 map 标记恶意 UA:

nginx
nginx
# 放在 http {} 内
map $http_user_agent $bad_bot {
    default 0;
    ~*SemrushBot             1;
    ~*meta-externalagent     1;
    ~*meta-externalfetcher   1;
    ~*ClaudeBot              1;
    ~*anthropic-ai           1;
    ~*Bytespider             1;
    ~*AhrefsBot              1;
    ~*MJ12bot                1;
    ~*DotBot                 1;
    ~*(python-requests|Go-http-client|libwww-perl) 1;
}

然后在需要保护的 server 块里拦截:

nginx
nginx
server {
    listen 443 ssl;
    server_name 你的域名;

    # 命中恶意 UA 直接断连
    if ($bad_bot) {
        return 444;
    }

    # 其余正常配置 ...
}

注意:Nginx 配置里 if 在 location 内容易踩坑,但在 server 层做简单的 return 是安全的官方用法。改完先测试再重载:

Bash
Bash
sudo nginx -t && sudo systemctl reload nginx

UA 名单按自己日志里实际出现的补,~* 表示不区分大小写。如果你希望自己的内容被某些 AI 检索,就别把对应 Bot 加进去。

第四步:拦截敏感路径扫描

扫描器最爱探测的路径,也直接 444:

nginx
nginx
server {
    # ...

    # 常见敏感文件 / 后台扫描
    location ~* /\.(env|git|htaccess|htpasswd) { return 444; }
    location ~* /(wp-login|wp-admin|xmlrpc\.php) { return 444; }
    location ~* /(phpmyadmin|pma|adminer) { return 444; }
    location ~* /(vendor|tmp|backup|config)\. { return 444; }
}

这里有个我实际踩过的点:location 的匹配顺序。Nginx 正则 location 按书写顺序匹配、第一个命中即停;如果请求在 server 层已被 rewrite 改写成别的 URI,再用 location 正则去拦原始路径可能拦不到。所以拦截规则要针对最终生效的 URI,或干脆在 server 层用 if ($bad_bot) 这种不受 rewrite 影响的方式处理 UA。

第五步:限速,兜底防刷

对没被直接拉黑、但请求过密的,做连接和请求限速:

限速处理未直接拦截的高频请求。
限速处理未直接拦截的高频请求。
nginx
nginx
# http 块定义限速区
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=addrlimit:10m;

server {
    limit_req zone=general burst=20 nodelay;
    limit_conn addrlimit 20;
}

rate=10r/s 是平均每秒 10 个请求,burst=20 允许短时 20 个排队,正常访客无感,脚本狂刷会被挡。

验证效果

重载后,用被封的 UA 本机测试:

Bash
Bash
# 用恶意 UA 请求,应直接被断开(无响应)
curl -A "SemrushBot" -I https://你的域名/

# 正常 UA 请求,应返回 200/301
curl -A "Mozilla/5.0" -I https://你的域名/

再观察面板流量和 access.log,被拦的请求不再产生响应流量,上行明显回落。也可以统计日志里 444(若记录了的话)的数量确认命中。

顺手整理的安全清单

结合这次迁移,给服务器定的几条基础防护:

  1. 只开放必要端口,面板、数据库不直接暴露公网;数据库只监听 127.0.0.1;
  2. phpMyAdmin 等管理工具不开公网,需要时通过 SSH 隧道或反代 + 访问限制进入;
  3. SSH 换非默认端口、禁用密码登录改用密钥、限制 root 直接登录;
  4. 面板用强密码 + 安全入口,及时更新面板和插件;
  5. Nginx 层拦恶意 UA、敏感路径,并做限速;
  6. 网站目录权限最小化,删掉不用的站点和默认页;
  7. 定期自动导出数据库、异地备份,备份文件不放在 web 可访问目录;
  8. 定期看一眼流量和日志,异常刷量早发现。

小结

防爬虫刷量的关键是先看日志、确认是谁,再在 Nginx 层处理:恶意 UA 和敏感路径用 return 444 直接断连、不产生流量,其余靠限速兜底。免费额度有限,与其等流量超了,不如在入口就把无意义的抓取掐掉。

全文完
全站文章均为原创,转载请保留署名和出处。
阅读 2 次