Summary
- RFC 9931 把 HTTP/1.1 协议切换中的两件事重新分开:客户端发完 Upgrade 或 CONNECT 请求,只是完成了提议;收到本次请求对应的
101 Switching Protocols或成功 2xx,才确认这条连接已经进入新协议或隧道状态。 - 当受信任的 HTTP 客户端在确认前放行由不受信任第三方选择的字节,拒绝切换的服务器可能把这些字节当成下一条已认证 HTTP 请求。治理所需的不是保存敏感负载,而是留下切换边界凭据:何物被暂存、何种响应到达、哪条规则开闸、最终由哪个解析器接管。
快路径提前花掉的是确定性
“乐观发送”解决的是真实成本。若服务器大概率同意协议切换,客户端等待一轮响应才开始传输,看起来只是平白增加时延。于是它先完成请求,再立即发送预期由新协议消费的数据;猜对时,业务更快进入有效阶段。
RFC 9931 关注的是猜错之后的语义,而不只是重试代价。这份文件于 2026 年 3 月在 IETF 流发布,属于标准轨文件,并更新 RFC 9112 与 RFC 9298。它没有笼统否定性能优化,而是指出:在同一条 HTTP/1.1 连接上,“已经提出切换”与“服务器已经接受切换”是两个不能合并的事件。
Upgrade 允许客户端请求在现有连接上改用另一种应用协议。服务器以 101 Switching Protocols 表示理解并愿意执行,还要说明响应之后采用什么协议。CONNECT 则请求代理建立隧道;成功 2xx 表示响应头结束后进入隧道模式。任何非成功响应都意味着隧道尚未形成。
原有 HTTP 语义已经要求客户端先完整发完 Upgrade 请求,不能在一个消息中途换语法。RFC 9931 补上另一半:请求完成是必要条件,却不是充分条件。服务器可能不支持该令牌,可能要求认证,也可能拒绝端口、目的地或资源,甚至只是不认为切换有收益。在响应到来之前,客户端拥有的是判断,不是连接状态事实。
成功率属于预测,不属于本次响应
历史经验当然有价值。最近一次同类切换成功、能力探测为绿、供应商文档声明支持、拒绝率长期很低,这些信息都可以用于容量设计、灰度分组和时延预算。把它们全部丢掉并不会更安全。
问题发生在证据换位。上一次成功以后,路由、后端、凭据、目的策略或中间代理可能已经变化;即使配置完全未变,远端服务也可能临时不可达。更根本的是,协议把本次请求的接受权留给本次服务器。统计概率再高,也不能生成一条尚未收到的肯定响应。
运维语言很容易掩盖这种换位。“这个代理支持 CONNECT”慢慢变成“这个 CONNECT 已成功”;“令牌已在 IANA 注册”被误听成“端点当前接受”;“一直都能用”最终成为提前放行数据的默认依据。每一次缩写都删掉了连接、请求、响应或时间中的一个限定词。
应当并列保存两类事实。第一类是预测证据:软件版本、以往结果、文档与测试。第二类是当前状态证据:HTTP 版本、连接轮次、本次响应与选定协议。它们可以高度相关,却无法互相替代。前者帮助人决定是否尝试优化,后者才决定下一批字节应由谁解释。
同一批字节可能突然换了“作者”
RFC 9931 并没有说所有两方通信都会出现同样的安全问题。如果连接两端本来就准备接收对方任意数据,预测失误可能只是一次协议失败。真正危险的结构是三方:服务器信任 HTTP 客户端,但客户端转发的数据由另一个不受信任的应用选择。
设想一个本地应用要求已认证代理客户端建立 TCP 隧道。应用立刻交出原本要发给远端服务的数据,代理客户端也在收到 CONNECT 结果之前将其转发。此时目的地建立失败,服务器拒绝 CONNECT,并继续在原连接上等待下一条 HTTP/1.1 请求。
若恶意应用把自己的数据排列成一条合法 HTTP 请求,服务器就可能把它当作受信任客户端发出的后续动作。连接也许通过客户端证书获得了连接级身份,第三方数据因而继承了不属于自己的身份。RFC 9112 把更广泛的“请求走私”描述为:利用不同接收方的解析差异,隐藏原本会被策略阻止的请求。
这里至少有三种失败。预测失败——切换没有发生;分帧失败——发送方与接收方选择了不同语法;归属失败——第三方选择的字节被记在另一主体名下。只统计 Upgrade 或 CONNECT 的拒绝数,只看到了第一层。
即使那批字节不足以组成完整请求,它们也可能进入一个建立在“输入来自可信 HTTP 客户端”假设上的解析器。公开资料没有证明任何具体产品存在漏洞,也没有给出实际攻击频率。它们证明的是一个条件结构:确认前放行会改变谁能向旧解析器供给数据。
不同协议用不同方式购买低时延
WebSocket 已经选择不走这条捷径。客户端发送开场握手后,必须等待并验证服务器响应,之后才能发送更多数据。客户端到服务器的帧还使用高熵掩码。这两项设计分别约束发送时机与字节形态。
RFC 9298 原本允许客户端在收到 UDP 代理响应前乐观发送数据包。RFC 9931 现在把允许范围收窄到 HTTP/2 或更高版本,明确禁止 HTTP/1.x 下这样做。IP over HTTP 的 RFC 9484 采用相同边界:HTTP/2、HTTP/3 可以有条件提前发送,HTTP/1.x 不行;把新版本请求转换成 HTTP/1.1 的中间设备,必须等成功响应解析完毕后才可转发胶囊。
差异来自连接结构。在 HTTP/1.1 中,请求严格顺序排列,后一条请求的起点隐含在前一条的结束位置。HTTP/2 和 HTTP/3 用明确的流标识区分请求。因此,某次被拒切换的数据不会自然落进“下一条 HTTP/1.1 请求”的语法位置。这只排除了此处的特定歧义,绝不等于新版本、隧道目标或隧道内应用获得了全面安全认证。
RFC 9931 还给未来 Upgrade 令牌三种设计方向:禁止确认前发送;让新协议以固定前导开始,使 HTTP/1.1 解析明确失败;或者使用高熵掩码。若切换后不再保留原 HTTP 方法的语义,限定为无内容 GET 也能减少可能被两种语法争夺的数据。
IANA HTTP Upgrade Token 注册表承担的是命名与引用功能。它帮助各方知道一个令牌指向哪份规范,却不观察某条实时连接。注册存在不能证明端点现在支持,更不能证明当前请求已经获准切换。
CONNECT 的拒绝路径需要两侧共同收口
当 HTTP/1.1 代理客户端代表一个不受信任 TCP 客户端工作时,RFC 9931 要求它至少采取两种行为之一。第一,等到成功 2xx 后再转发 TCP 负载。第二,在请求中加入 Connection: close,使拒绝结果同时终止连接,不给提前到达的字节留下“下一条 HTTP 请求”的位置。两者可以并用。
拒绝请求的代理服务器也承担收口责任:它必须关闭底层连接,不得继续处理这条连接上的请求。这项防线保护服务器免受过早转发客户端的影响,却确实可能损失性能,尤其在 407 认证挑战后,本可复用的连接需要重建。
因此 RFC 留出一个例外:若服务器知道某客户端会等待 2xx,可以关闭拒绝即断连的缓解措施,并指出可用 User-Agent 与供应商文档识别合规客户端。这里的“知道”应谨慎理解。RFC 9110 把 User-Agent 定义为发起请求的软件产品信息,也劝实现者不要冒充别的产品;它没有把字段变成密码学身份凭证。
合理的性能例外必须可到期、可撤销。记录至少应包括产品与版本范围、被审阅的供应商声明、本地验证、覆盖的中间设备、负责人、复核日期与回滚条件。一次升级足以改变发送顺序,“已知合规”不能成为永不失效的标签。
切换确认凭据只保存边界
解决切换的响应已经存在于线上,缺口常出现在运维记录:尝试切换、放行第三方字节与最终解析状态分散在不同日志里,彼此无法关联。Daniel Kade 建议在风险路径上保留一份紧凑的“切换确认凭据”。
第一部分标识连接轮次和 HTTP 版本,记录机制是 Upgrade 还是 CONNECT、所请求的令牌或隧道类型,并以受保护引用表示目标。它将后续数据来源分为自有控制、受限子系统或不受信任第三方,不复制真实负载。
第二部分记录闸门。哪个实现版本和哪条策略决定字节何时放行?它是否等待 101 或 2xx,是否要求断连,是否依赖固定前导、掩码或明确分离的 HTTP/2、HTTP/3 流?响应前是否真的转发过数据;如果转发,依据的是哪种规范允许的结构,而不是一句“通常成功”?
第三部分绑定结果:响应类别、实际选定协议、最终解析器或隧道状态、拒绝后的连接处置与任何遏制动作。例外项附带证据、范围、批准人、到期日和失效触发器。客户端、服务器、中间链、认证方式或策略一旦变化,就开启新判断,不静默继承旧结论。
凭据不保存隧道内容、密码、授权头、客户端证书或应用秘密。摘要与结构化状态足以回答治理问题:是哪一个当前事件允许这些字节从一种解释边界跨到另一种?
这不是 RFC 9931 的新字段,也不是 IETF 对企业流程的要求,而是一个本地责任工具。它还要阻止反方向的夸张:CONNECT 的 2xx 证明隧道形成,不证明隧道内每项业务活动都已获授权。后一层仍有自己的身份与政策判断。
证据止步之处
冻结来源给出了协议语义和条件性风险,没有指认任何厂商漏洞、生产事件或部署比例,也无法说明错误实现有多普遍。缓存、断连、固定前导、升级 HTTP 版本各有代价,不能从一份 RFC 推导出所有系统的唯一答案。
时延不是虚构问题。等待会增加响应时间,断连会增加认证与握手成本,缓存第三方数据也会消耗资源。可治理的优化不是没有成本,而是失败时仍保留清晰语法、明确归属和修正路径。
因此结论可以保持很窄:过去成功能够改善预测;本次响应与本次连接状态,才确认下一批字节进入了什么协议。
Sources
- RFC 9931:HTTP/1.1 乐观协议切换的安全考量
- RFC Editor 的 RFC 9931 信息页
- RFC 9110:HTTP 语义
- RFC 9112:HTTP/1.1
- RFC 9298:通过 HTTP 代理 UDP
- RFC 6455:WebSocket 协议
- RFC 9484:通过 HTTP 代理 IP
- RFC 9113:HTTP/2
- RFC 9114:HTTP/3
- IANA HTTP Upgrade Token 注册表
- Heng Lu,《The Policy Mirror》
- Heng Lu,《Minimum Initial Specification, Localized Future Decision, Voluntary Adoption》
- Heng Lu,《On Why BTW Media Exists, and Why Reality, Not Advocacy, Is the Product》
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
