⭐ 推荐:社区规则条款 V1.0

怎么用 Nginx 的 return 403 和 444 拦截爬虫有什么区别?

GJ论坛站长
GJ论坛站长 管理员资深会员 👑黑卡会员
发布于 2026-10-21 21:01 ·13 浏览 ·0 回复
内容摘要

Nginx 的 return 403 返回完整拒绝响应,444 不发送响应直接断开 TCP 连接;拦截恶意爬虫优先用 444 以省带宽并避免暴露规则,需让搜索引擎、监控或可能误伤流量识别拒绝时用 403。

结论:403 会返回一个完整的 HTTP 响应(状态码 + 响应头 + 错误页正文),告诉对方「我被拒绝了」;444 是 Nginx 独有的非标准状态码,它不发送任何响应,直接关闭 TCP 连接,对方只会看到「连接被断开」。拦截恶意爬虫优先用 444(省带宽、不暴露服务信息),需要让搜索引擎、CDN、监控明确识别「这是主动拒绝」时用 403。

403 和 444 在 Nginx 里的本质区别是什么?

结论:403 是标准 HTTP 语义,返回可读的拒绝响应;444 是 Nginx 内部约定的「不发响应直接断连」指令,客户端拿不到状态码。

具体差异有四点:一是响应内容,return 403 默认带 Server: nginx 头和约 150–160 字节的默认错误页,return 444 一个字节都不发,$body_bytes_sent 记为 0;二是连接行为,403 之后连接正常收尾、可以被 keep-alive 复用,444 直接掐断连接;三是可识别性,403 在浏览器、curl、搜索引擎、监控里都能被正确解析,444 在多数客户端表现为「空响应」异常;四是兼容性,444 只有 Nginx(及 OpenResty、Tengine 等衍生版)认,Apache、Caddy、IIS 没有这个码,上游负载均衡的健康检查也可能把它当成服务故障。

怎么用 curl 验证两种返回的差别?

结论:curl -I 看 403 会打印完整响应头,看 444 会报 curl: (52) Empty reply from server,这一条命令就能把两者区分开。

curl -I https://example.com/test.html          # 返回 HTTP/1.1 403 Forbidden + Server: nginx
curl -v https://example.com/test.html          # 444 场景:Recv failure / Empty reply from server

-I 发 HEAD 请求,能直接看到状态行;-v 会打印握手与收包过程,444 场景下你会看到请求发出去了,但对方一个字节都没回就关闭了连接。用浏览器直接访问 444 的地址也一样,Chrome 显示 ERR_EMPTY_RESPONSE,而不是 403 页面。

拦截爬虫用 403 还是 444?按场景选

结论:纯恶意、高频、明显是脚本扫描的流量用 444;可能被误伤、需要留证据或需要对方「看懂」的流量用 403。

推荐 444 的对象:空 User-Agent、python-requests、scrapy、curl、wget、Go-http-client、sqlmap、masscan 这类明显的工具指纹,以及已知的采集器 UA。原因是它们本来就不看你的错误页,返回 403 的正文纯属浪费带宽,而且 403 相当于告诉对方「你被识别了」,攻击者会立刻换 UA 或加代理;444 不给任何反馈,更难试探规则。

推荐 403 的对象:搜索引擎(百度、Google、Bing)、第三方监控、支付/回调类合法机器人、以及可能被规则误伤的真实用户。因为 403 会让搜索引擎明确知道你拒绝抓取,抓取预算的消耗是可控的;而 444 属于「连接失败」,谷歌、百度可能判定为服务器异常并提高重试频率,反而放大请求量。

另外提醒一点:444 是在 HTTP 层关闭连接,TLS 握手已经完成,所以 HTTPS 站点用 444 并不能省下 TLS 开销。真要挡在握手之前,得在 iptables/nftables 或 CDN 的 WAF 层做。

403 / 444 的 Nginx 配置怎么写?

结论:用 map 做 UA 匹配、在 server 块里 if 加 return,是既能批量维护规则又不会触发 if 坑的写法。


map $http_user_agent $bad_bot {
    default 0;
    ""      1;
    ~*(python-requests|scrapy|curl|wget|sqlmap|masscan|Go-http-client) 1;
}

server {
    listen 443 ssl;
    # return 在 if 内是安全用法
    if ($bad_bot) {
        return 444;
    }

    location / {
        # 需要明确告知的路径,比如 API 或需要留证的接口
        if ($bad_bot) {
            return 403;
        }
        ...
    }
}

补充两条可搭配的参数:限流被触发时的默认状态码是 429,可以通过 limit_req_status 444; 改成静默断连,但这样做会让前端排障变困难,建议只在高频扫描严重的站点开启;deny all; 的默认行为等同 403,不能返回 444,要用 return 444 才能实现静默拒绝。改完执行 nginx -t && nginx -s reload 生效,规则命中情况看 access log 里的状态码字段,444 的请求会以状态码 444 记录下来,方便统计。

用 444 有哪些坑?

结论:444 不是万能拦截,主要风险是误伤、可观测性变差和中间层不认。

一是误伤难排查:用户反馈「打不开、没反应」时,你看到的只是一条 444 日志,没有任何页面提示,售后成本高;建议先在测试环境用小流量验证 UA 规则,用 curl -A "python-requests/2.31" 复现命中。二是 CDN/反向代理层:如果站点前面还有 CDN 或 SLB,444 这种非标准码能否透传取决于厂商,部分健康检查会把 444 当不健康,直接摘节点。三是监控统计:403 能自然进入「4xx 错误率」指标,444 常被算成连接异常,告警规则要提前调整。四是不要把 444 用在需要 SEO 友好的路径上,对搜索引擎保持 200 或明确的 403/404,比静默断连安全得多。

总的说:444 是「掐线」,成本低、信息少、只适合确定是恶意流量的场景;403 是「明说」,可解释、可观测、对搜索引擎友好。实战里建议两条规则并存——脚本指纹和空 UA 走 444,搜索引擎白名单放行,其余可疑流量先观察日志再收紧。

本文转载自 GJ站长论坛,原文地址:https://www.gj0.com/thread-2363.html
转载请注明出处,版权归原作者所有。
他们都看过 1 人浏览过
GJ论坛站长
—/ 5暂无评分
还没有评分,来打第一分吧

全部回复 0

还没有回复,来抢沙发~