在爬虫开发中,403 Forbidden 是最常见也最棘手的问题之一。很多开发者的第一反应是 “反爬封了 IP”“User-Agent 不对”,但改完 UA、挂上代理之后,403 依然反复出现。本质原因是:现代反爬体系早已突破了应用层特征校验,下沉到了协议栈全层级的指纹识别—— 你的请求从 TCP 握手开始,就已经暴露了 “非浏览器客户端” 的身份。

本文将从 HTTP 应用层、TLS 传输层、HTTP/2 帧层、TCP 网络层四个维度,逐层拆解爬虫触发 403 的协议级根本原因。

一、HTTP 应用层:最容易被忽略的基础协议合规性

HTTP 协议本身有严格的格式规范和语义约定,大量初级爬虫的 403 都源于违反了基础协议规则,而非主动的反爬策略。

1. 请求行与强制头部缺失

HTTP/1.1 协议明确规定,所有请求必须携带 Host 头部,用于区分同一 IP 下的多虚拟主机。很多手写 Socket 爬虫、或者封装不当的请求库,会遗漏 Host 头,或者 Host 值与目标域名不匹配,服务端直接返回 403 拒绝访问。

同时,HTTP 方法与路径的合规性也会触发拦截:例如接口明确要求 POST 请求,爬虫误用 GET;路径中的特殊字符未执行标准 URL 编码,导致服务端解析失败,直接判定为非法请求。

2. 请求头顺序与集合特征

浏览器的请求头存在固定的排列顺序,例如 Chrome 通常按照 HostConnectionCache-ControlSec-Ch-UaUser-Agent 的顺序发送头部。而 Python requests、原生 curl 等爬虫常用库,会按照字典传入顺序、或者库内默认排序发送头部,顺序特征与浏览器完全不同。

WAF(Web 应用防火墙)可以直接提取请求头的排列顺序、缺失的标准头部(如 AcceptAccept-LanguageSec-Fetch-* 系列)作为识别特征。哪怕你把所有头部都抄了一遍,只要顺序不对,依然会被标记为爬虫并返回 403。

3. 会话与 Cookie 协议逻辑

HTTP 是无状态协议,正常用户的访问流程必然是 “访问首页 → 服务端下发 Cookie → 携带 Cookie 访问子页面 / 接口”,这是浏览器默认的会话协议逻辑。

很多爬虫跳过首页初始化,直接携带构造的 Cookie 请求业务接口,或者 Cookie 的字段顺序、过期格式、编码方式不符合浏览器规范,服务端会判定会话非法,直接返回 403。特别是带 CSRF Token 的接口,Token 与 Cookie 的绑定关系不匹配,本质就是违反了应用层的鉴权协议。

4. 实体头部与内容编码不匹配

POST 请求中,Content-Type 与请求体格式必须严格对应:表单提交对应 application/x-www-form-urlencoded,JSON 提交对应 application/json,文件上传对应 multipart/form-data。一旦类型不匹配,服务端无法解析请求体,直接返回 403。

同时,Content-Length 计算错误、Transfer-Encoding: chunked 分块格式不符合规范、Content-Encoding 声明的压缩方式与实际不一致,都会触发协议层面的拦截。

二、TLS 层:90% 无痕爬虫栽在这里的指纹坑

当你改全了所有 HTTP 头部、换了代理 IP 依然返回 403 时,90% 的概率是 TLS 握手指纹被识别了。这是当前反爬最核心、也最隐蔽的协议层识别手段。

1. JA3 客户端指纹

TLS 握手的第一步,是客户端发送 Client Hello 包,包中包含:支持的 TLS 版本、密码套件列表、扩展列表、椭圆曲线列表、椭圆曲线点格式等信息。

不同客户端(Chrome、Firefox、Python requests、curl)的加密库实现不同,上述字段的组合、排列顺序完全不同。将这些信息按规则拼接后做 MD5 哈希,就得到了唯一的 JA3 指纹

例如 Python requests 依赖的 urllib3 库,默认的密码套件数量、排序、扩展项与 Chrome 浏览器差异极大,WAF 只需要对比 JA3 指纹库,就能直接识别出爬虫客户端,静默返回 403,这也是 “所有头都仿了还是被封” 的核心原因。

2. TLS 扩展项特征

除了整体 JA3 指纹,单个扩展项的细节也会暴露身份:

  • SNI 扩展:服务器名称指示,用于在同一 IP 上部署多域名 HTTPS 证书。很多底层爬虫未开启 SNI,或者 SNI 与访问域名不一致,服务端直接拒绝握手。
  • ALPN 扩展:应用层协议协商,浏览器会携带 h2, http/1.1 声明支持 HTTP/2,而大量爬虫库默认不携带 ALPN 扩展,或者只声明 http/1.1,特征极其明显。
  • 证书校验行为:爬虫为了绕过证书错误,常开启 “跳过证书验证” 选项,这一行为会在 TLS 握手中暴露特征,被高等级 WAF 直接标记为风险客户端。

3. TLS 版本与降级风险

当前主流网站已强制要求 TLS 1.2 及以上版本,部分站点已全面切换 TLS 1.3。如果爬虫使用的加密库版本过旧,默认协商 TLS 1.0/1.1 版本,会直接被服务端拒绝,返回 403。

同时,部分爬虫会触发 TLS 降级攻击特征:客户端明明支持高版本 TLS,却主动协商低版本,会被 WAF 判定为恶意流量拦截。

三、HTTP/2 协议层:帧级特征的精准识别

随着 HTTPS 站点全面升级 HTTP/2,协议层的识别维度进一步下沉到了帧级别,传统 HTTP/1.1 爬虫的特征越来越明显。

1. 伪头顺序差异

HTTP/2 不再使用明文请求行,而是用 :method:authority:scheme:path 四个伪头表示请求行信息。不同客户端的伪头排列顺序有固定规律:

  • Chrome 顺序::method:authority:scheme:path
  • 大部分 Go 语言 HTTP/2 库::authority:method:path:scheme

WAF 只需提取伪头顺序,就能快速区分真实浏览器与自研爬虫,返回 403。

2. 帧行为与流控参数特征

HTTP/2 基于二进制帧传输,不同实现的帧发送行为存在本质差异:

  • SETTINGS 帧参数:连接建立后,客户端会发送 SETTINGS 帧声明流控参数,比如最大并发流数、初始窗口大小、帧最大长度。Chrome、Firefox、各类语言的 HTTP/2 库的默认参数完全不同,形成独特的帧指纹。
  • 优先级帧与流依赖:浏览器会为不同资源设置流优先级,发送 PRIORITY 帧,而绝大多数爬虫库不会发送优先级帧,或者流依赖逻辑与浏览器不一致,是非常强的爬虫特征。
  • 帧发送顺序:浏览器的 SETTINGS、WINDOW_UPDATE、HEADERS 帧有固定的发送时序,而爬虫库的帧时序通常更简单、更规律,极易被识别。

四、TCP 传输层:最底层的操作系统指纹

哪怕你完美模拟了上层所有协议,TCP 协议栈本身的特征依然会暴露你的身份 —— 因为 TCP 参数由操作系统内核决定,服务器机房的 Linux 系统,和用户端的 Windows/macOS 系统,内核参数差异极大。

1. TCP 初始窗口与选项指纹

TCP 三次握手的 SYN 包中,携带了 MSS(最大分段大小)、窗口缩放因子、SACK 选项、时间戳等参数。不同操作系统的内核默认配置不同,这些参数的组合形成了 TCP 指纹(也叫 p0f 指纹)

例如:

  • 桌面端 Windows 系统的初始窗口大小通常为 65535,TTL 默认 128
  • Linux 服务器系统初始窗口多为 29200,TTL 默认 64

服务端可以通过 SYN 包的 TCP 选项特征,直接判断请求来自服务器机房的爬虫,还是普通用户的终端设备,对机房 IP 段的请求直接返回 403。

2. 连接行为的协议特征

除了握手参数,TCP 连接的行为模式也属于协议层识别范畴:

  • 连接复用逻辑:浏览器会复用同一个 TCP 连接,串行 / 并行请求多个资源(HTML、CSS、JS、图片),符合 HTTP keep-alive 的标准使用逻辑;而多数爬虫是单次请求建立一次连接,用完即关,行为特征极其明显。
  • 并发与时间规律:浏览器的 TCP 并发数受协议限制(HTTP/1.1 同域名最多 6 个并发连接),而爬虫经常开启几十上百个并发连接,瞬间建立大量 TCP 会话,直接触发服务端的连接数限流,返回 403。

五、协议层视角的 403 解决思路

理解了各层级的协议特征,解决 403 的核心逻辑就非常清晰:从下到上,逐层对齐真实浏览器的协议指纹,而非只修改表层的 User-Agent。

  1. HTTP 层:严格对齐目标站点浏览器的请求头顺序、头部集合、Cookie 生成逻辑,遵循正常用户的会话访问流程,不要跳过初始化步骤。
  2. TLS 层:放弃原生 requests、urllib 等指纹特征明显的库,使用 curl-impersonatehttpx(配置 TLS 模拟)、playwright/selenium 等工具,完美复刻浏览器的 JA3 指纹与扩展特征。
  3. HTTP/2 层:优先使用基于 Chromium 内核的工具发起 HTTP/2 请求,避免使用自研或原生 HTTP/2 客户端,防止帧级特征暴露。
  4. TCP 层:使用住宅代理 IP 替代机房代理,从源头解决操作系统指纹与 IP 属性问题;高要求场景下可调整内核 TCP 参数,对齐桌面端系统特征。

本质上,爬虫与反爬的对抗,早已从 “规则绕过” 升级为 “协议级身份模拟”。只有深入理解每一层协议的细节,才能从根本上解决反复出现的 403 问题,而不是停留在 “换 IP、改 UA” 的表层调试。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐