HTTP 代理语义与浏览器请求
了解浏览器如何使用 HTTP 代理、CONNECT 隧道、标头、重定向和 DNS,以便可靠配置代理。
为什么代理语义在浏览器中很重要
HTTP 代理会改变浏览器到网站的路由、请求形式以及名称解析位置,因此会影响认证、Cookie、重定向、TLS 证书、缓存和日志。标准定义了报文语法,但部署仍可限制目标、改写标头和记录元数据。应把代理视为有明确契约的网络服务。
HTTP 代理不只是放在浏览器和网站之间的一个地址。它会改变路由、请求形式,有时也会改变名称解析的位置。这些细节会影响认证、Cookie、重定向、TLS 证书、缓存、日志以及请求显示的来源。启动命令看起来正确,并不代表线上报文交换就符合应用预期。
浏览器使用 HTTP 或 HTTPS 代理时,请求语义会影响认证、Cookie、重定向、TLS 证书、缓存、日志以及请求显示的来源。本文依据标准和可观察行为,不绑定任何特定厂商。实际配置可参考浏览器代理配置:SOCKS5、HTTP 与 HTTPS 指南。如果部署还使用 WebRTC,什么是 WebRTC IP 泄漏?介绍了 HTTP 代理设置不会自动控制的另一条流量路径。
要点是:普通转发请求常使用绝对 URI;隧道内请求使用源形式;CONNECT 为主机和端口建立字节隧道;代理认证和源站认证使用不同挑战;DNS 可能由本地或代理解析。重定向、service worker、缓存和非 HTTP 协议会产生额外请求。
发往代理的请求可以使用绝对 URI,而通过隧道发送的请求使用源形式。CONNECT 成功后,代理通常只转发加密 TLS 字节,不解析其中的 HTTP 消息。代理认证和源站认证是不同的挑战,使用不同的标头。浏览器可能在本地解析主机名,也可能让代理解析,具体取决于协议和实现。重定向、Service Worker、缓存和非 HTTP 协议会产生简单测试容易遗漏的请求。
请求形式与第一跳
RFC 9110 第 7.1 节定义四种 request-target 形式。通过转发代理访问 HTTP 资源时,浏览器可以发送 absolute-form:
GET http://shop.example/products HTTP/1.1
Host: shop.example
Accept: text/html
代理用完整 URI 选择下一跳,Host 标识源站 authority。直连源站时,请求行通常只有路径:
GET /products?sort=price HTTP/1.1
Host: shop.example
代理日志中的绝对 URI 只证明第一跳是转发代理,不说明源站收到相同形式。CONNECT 使用 shop.example:443 这样的 authority-form;OPTIONS * 指向服务器自身。
authority-form 供 CONNECT 使用,由主机和端口组成。asterisk-form OPTIONS * 指向服务器自身,而不是特定资源。普通页面加载很少生成它,但诊断或兼容性测试可能会使用。代理通常会把请求转换为下一跳所需的形式,因此抓包时应分别观察浏览器到代理和代理到源站的报文。
HTTP 与 HTTPS URL 的区别
http:// 请求可作为可读 HTTP 发给代理,代理能看到方法、路径、标头和状态。https:// 请求通常先发送:
CONNECT shop.example:443 HTTP/1.1
Host: shop.example:443
代理返回 200 Connection Established 后,浏览器在隧道中启动 TLS。加密路径、Cookie、授权和正文对普通代理不可见,但目标 authority、时间和字节数仍可见。代理拒绝 CONNECT、要求认证、禁止端口或解析失败时,源站没有 HTTP 响应。
对于 http:// URL,代理能够查看方法、路径、标头和响应状态。对于 https:// URL,HTTP 请求、响应标头和响应正文都在 TLS 内部,普通转发代理看不到。浏览器开发者工具可能显示网络错误,而不是普通状态码,因为故障发生在路由建立阶段。
HTTP/2 与 HTTP/3
RFC 9112说明 HTTP/1.1 报文边界。隧道建立后,浏览器与源站可能使用 HTTP/2 或 HTTP/3;每一跳的协议可以不同,诊断时应分开记录。
HTTP/2 使用二进制帧和 :method、:authority 等伪标头,HTTP/3 运行在 QUIC 之上。不要只根据 URL 推断每一对参与者之间使用的协议:接受 HTTP/1.1 CONNECT 的代理可以承载不透明的 HTTP/2 TLS 会话,理解 HTTP/2 的代理则可能使用扩展 CONNECT。
CONNECT 隧道、TLS 与名称解析
CONNECT 的目标是主机和端口,不是带路径的 URL。成功后代理从处理 HTTP 报文切换为双向转发。普通 HTTPS 隧道中代理可见目标和连接元数据,不能读取加密请求;它仍可按目标限制端口或关闭连接。端到端证书由浏览器验证;TLS 检查属于需要单独记录的信任架构。
代理能看到什么
在普通 HTTPS 隧道中,代理能看到发给代理本身的请求,包括目标主机和端口,也能观察连接元数据。它无法读取加密的 HTTP 路径、Cookie、授权值或响应正文,但仍可根据目标执行策略、限制端口、限制连接时长或关闭隧道。
浏览器会检查源站主机的证书名称、有效期和信任链。除非部署刻意进行 TLS 拦截,否则不会涉及代理证书。拦截会改变信任模型,需要浏览器配置文件信任相应的证书颁发机构,应作为独立架构记录和测试。SNI 及其他 TLS 握手细节也可能向网络观察者暴露目标主机。
DNS 在哪里发生
浏览器可能把主机名交给代理解析,也可能先由本地解析器处理。代理侧解析只改变查询归属,不能保证预取、扩展、门户检查或其他辅助请求使用同一路径。需要确认 DNS 位置时,应测试冷 profile、新进程、重定向、iframe、worker 和失败查询,并参考 MDN HTTP 概览。
本地解析意味着本地解析器可能知道目标,即使后续 TCP 连接使用代理。证书吊销检查、强制门户检查、DNS 预取、推测性连接和扩展都可能有独立的网络行为,因此不能从一次地址栏导航推断所有 DNS 流量。
标头、认证与转发策略
RFC 9110 第 5 节区分不同标头和逐跳字段。
代理认证不等于源站认证
需要凭据的代理返回 407 Proxy Authentication Required 和 Proxy-Authenticate,客户端使用 Proxy-Authorization。源站登录则返回 401 Unauthorized,使用 WWW-Authenticate,客户端发送 Authorization。HTTPS 常在 CONNECT 阶段遇到代理挑战。不要混用两类凭据,也不要在网页脚本中拼接;请使用浏览器或框架提供的受保护配置。
对于 HTTP URL,代理挑战可以在代理转发请求前到达;对于 HTTPS URL,挑战通常响应 CONNECT,发生在 TLS 开始前。浏览器可能使用凭据重试连接,但自动化库可能把挑战暴露为导航失败。两类凭据作用域不同,通常也由不同系统记录。
转发身份字段
Via、Forwarded 和 X-Forwarded-For 是否出现由代理策略决定。它们可能描述客户端地址、协议和主机,应用只能信任已知代理跳。浏览器不会保证代理添加某个字段;若无需原始地址,不要接受公共网络任意提交的转发值。
逐跳字段与端到端字段
Connection 可标记只能用于一跳的字段,代理应在转发前消费或移除。Cache-Control 等端到端字段按中间方规则传播。开发者工具中的标头不一定等于源站收到的标头,重要问题应同时检查两侧日志。
转发身份字段的信任边界:
Via、Forwarded 和 X-Forwarded-For 可能描述客户端地址、协议和主机。它们的出现是代理策略,而非浏览器保证。应用应只信任已知代理跳添加的字段,不要接受来自公共网络的任意转发值。
逐跳字段的调试方法:
浏览器开发者工具中看到的标头可能与源站收到的不同;代理也可能添加页面从未生成的字段。需要区分时,应抓取浏览器到代理的交换,并检查源站日志。
会产生额外请求的浏览器功能
页面会继续请求样式表、脚本、图片、字体、frame、worker、manifest 和 API。重定向会带来新的主机名、解析、认证和 TLS 隧道;Cookie 的域、路径、Secure 与 SameSite 规则影响后续请求。service worker 可能从缓存响应或访问隐藏的 API,因此没有网络条目不一定代表绕过代理。WebSocket 在握手后成为长连接,WebRTC 媒体和数据通道会联系 STUN/TURN,应参考 MDN WebRTC API单独验证。
一个 301、302、303、307 或 308 响应可能让浏览器向另一个 authority 发起新请求。新请求仍使用代理,但可能需要新的 DNS 查询、认证决定和 TLS 隧道。代理能看到普通 HTTP 中的 Cookie,但看不到隧道内 HTTPS 的 Cookie;只记录第一次请求的日志无法解释之后的状态变化。
Service Worker 安装后可以从缓存满足 fetch,也可以编程发起请求。没有网络条目可能只是无需访问网络;反过来,Service Worker 也可能联系文档源码中不明显的 API 主机。WebSocket 从 HTTP 握手开始,随后成为长连接双向流;WebRTC 使用 ICE,可能访问普通 HTTP 之外的 STUN 或 TURN 服务器。
实用验证方法
- 在干净 profile 中直连 HTTP 和 HTTPS,记录重定向后的 URL、状态、关键标头与协议。
1. 建立基线
在干净的浏览器配置文件中从直连开始,分别加载 HTTP 和 HTTPS URL,记录重定向后的最终 URL、状态、关键标头、协商协议和时间信息。比较代理变化时不要复用热缓存。
- 对 HTTP 确认代理收到 absolute-form;对 HTTPS 确认 CONNECT authority 和成功隧道。
407表示代理认证未完成,拒绝或超时表示源站尚未参与的路由问题。
2. 测试代理握手
使用代理访问日志或受控测试端点确认 HTTP 的 absolute-form、HTTPS 的 CONNECT authority 及成功的隧道响应。407 表示代理认证未完成;连接拒绝或超时表示源站参与之前的路由或策略问题。
- 让自有端点记录源地址、
Host、转发字段、协议版本和路径,并与代理日志比较。正常情况下源站看到的是代理出口地址。
3. 验证源站视角
让目标记录源地址、Host、转发字段、协议版本和请求路径,并与代理日志比较。路由正常时,源站应看到代理的出口地址,而不是浏览器本地地址,除非中间方刻意转发了该地址。
- 测试重定向、跨源图片、字体、iframe、worker、fetch、失败主机名以及同时有 IPv4/IPv6 记录的页面。
4. 执行请求图
测试包含重定向、跨源图片、字体、iframe、worker 和 fetch 调用的页面,加入失败的主机名以及同时拥有 IPv4 和 IPv6 记录的主机。这能揭示名称解析、地址族选择和代理认证在首个文档之外是否一致。
- 在已有 Cookie、service worker 和缓存后重跑;缺少网络条目可能只是缓存命中,实验之间应记录冷/热状态。
5. 使用热状态重复
在产生 Cookie、Service Worker 和缓存条目后重复相同导航,把网络请求与冷启动比较。请求消失可能表示命中缓存,而不是路由发生变化;受控实验之间应清理状态并记录所使用的状态。
应在干净配置文件中先建立直连基线,分别加载 HTTP 和 HTTPS URL,记录最终 URL、状态、关键标头、协商协议和时间。然后用代理日志确认 HTTP 的 absolute-form、HTTPS 的 CONNECT authority 及成功隧道;拒绝或超时表示源站参与之前的路由或策略问题。
让目标端点记录源地址、Host、转发字段、协议版本和请求路径,并与代理日志比较。再测试包含重定向、跨源图片、字体、iframe、worker、fetch、失败主机名以及 IPv4/IPv6 记录的页面,最后在 Cookie、Service Worker 和缓存存在时重复导航。
HTTP 成功而 HTTPS 失败时检查 CONNECT 认证、端口策略和证书;文档成功而 API 失败时检查 API 主机、CORS 与 service worker;部分域名失败时比较 DNS 和允许列表;源站看到意外地址时检查每一跳的转发字段。单独访问“我的 IP”页面不能证明完整路径。
常见症状及其含义
如果 HTTP 页面能加载而 HTTPS 失败,应检查 CONNECT 认证、目标端口策略和 TLS 证书错误。如果文档加载但 API 调用失败,应检查 API 主机名、CORS 响应以及调用是否由 Service Worker 处理。如果只有部分域名失败,应比较它们的 DNS 记录和代理允许列表。如果源站报告意外的客户端地址,应检查每个中间方对 Forwarded 和 X-Forwarded-For 的处理。
保持请求一致的配置选择
需要传统转发接口时使用 HTTP 代理;需要通用 TCP 中继时选择 SOCKS,并确认主机名解析位置。代理设置应只有一个权威来源,凭据通过浏览器或框架接口配置。若内容依赖地区,可使出口与应用期望相符,但语言、时区、DNS、WebRTC 和地址族仍可能独立变化。记录代理支持的协议和端口、DNS 位置、凭据轮换、添加的标头及日志保留期。识别每一跳、区分 407 与 401、理解 CONNECT 并覆盖完整请求图,能够在不依赖猜测的情况下排查浏览器请求。
不要把单个外部“我的 IP”页面当作完整测试。它通常只测一条 HTTP 路径,并且可能被缓存、重定向或由 CDN 提供。基于标准的检查加上两端日志,才能更有力地解释浏览器行为。记录代理接受的协议、允许的端口、DNS 解析位置、凭据轮换、添加的标头和日志保留期,才能把模糊的代理问题变成可测试的请求路径。
HTTP 页面能加载而 HTTPS 失败时,优先检查 CONNECT 授权、目标端口策略和 TLS 证书错误。文档加载而 API 失败时,检查 API 主机、CORS 响应以及是否由 Service Worker 处理。只有部分域名失败时,比较 DNS 记录和代理允许列表。
对于源站报告的意外客户端地址,应逐跳检查 Forwarded 与 X-Forwarded-For。不要把一个外部“我的 IP”页面当作完整验证,因为它可能只测一条被缓存、重定向或由 CDN 提供的 HTTP 路径。