遇到 421 Misdirected Request?SNI、Host 与连接复用怎么查
HTTP 421(Misdirected Request)表示服务器不愿或不能为这次请求的目标提供权威响应。排查时应先核对完整 URL、请求名称与连接上下文,再检查连接复用;它本身不是“节点带宽不足”或“代理密码错误”的证明。
本文适用于通过 VPN、代理或直连访问 HTTPS 页面时收到 421 的情况。需要区分“已经收到 HTTP 响应”和“TLS 握手就失败”:两者应查的阶段不同。
421 到底是谁拒绝了什么?
RFC 9110 第 15.5.20 节说明,源站或代表源站的网关可以用 421 拒绝与其服务范围、连接上下文不匹配的目标 URI。标准还规定,正向代理不应自行生成 421;但它可以转发上游的响应。
因此,“开代理时看见 421”并不能单独证明响应由代理节点产生。应结合发生阶段及对应日志,检查是访问的网站、入口网关,还是其他环节返回了这个结果。错误页中的一个产品名称,也不足以还原整条链路。
SNI、Host 和目标 IP 不是同一项
| 信息 | 所在阶段 | 主要用途 |
|---|---|---|
| 目标 IP 与端口 | 建立连接 | 决定连接到哪个网络端点 |
| TLS SNI | TLS 握手 | 向 TLS 服务端说明希望访问的服务器名称 |
| HTTP/1.1 Host | HTTP 请求 | 标识请求所面向的主机及相应端口信息 |
HTTP/2 :authority |
HTTP 请求控制数据 | 传递目标 URI 的 authority 部分 |
SNI 位于 ClientHello 中,见 RFC 6066 第 3 节。HTTP/2 的 :authority 与 Host 的关系则见 RFC 9113 第 8.3.1 节。它们分属不同层次,不能把“手动改一个 Host 请求头”理解成同时改好了 SNI、证书验证和后端映射。
普通访问先保留网站原始域名。不要用“把网址换成 IP,再跳过证书检查”替代诊断:这会改变请求条件,无法说明原域名为什么收到 421。若实际报错是证书名称不匹配,应先按时间、SNI 与信任链检查处理。
为什么 HTTP/2 连接复用也会遇到 421?
RFC 9113 第 9.1.1 节允许在满足服务权威性等条件时,用已有连接处理不同 URI authority 的请求;HTTPS 还需要证书对目标主机有效。标准同时指出,某些使用 SNI 选择后端的部署,可能在复用时把请求送到不合适的源站。
一个具体例子来自 Apache mod_http2 文档:多个虚拟主机共享证书时,若相关 TLS 协议、密码套件或客户端验证设置不一致,可能返回 421。这说明“证书涵盖两个域名”不等于两者在同一连接上一定具有兼容配置。
这是特定实现的例子,不代表所有 421 都来自 Apache,也不意味着看到 h2 就能确定是连接复用故障。
按四步收集能解释问题的证据
1. 找到真正失败的请求
记录完整域名、端口、请求方法、状态码和时间。首页、登录接口、脚本可能属于不同主机,不要把首页成功当成所有请求成功。
在浏览器开发者工具的 Network 中查看失败行的请求地址和协议;操作可结合本站HTTP/3、HTTP/2 与代理路径核对。反馈时去掉 URL 令牌、Cookie 和身份凭据。
2. 建立新连接对照
对于普通页面 GET,可以在保存必要内容后完全退出浏览器,再重新打开同一地址,记录首次访问与后续访问的差异。普通刷新或清缓存不应被当成“所有旧连接都已经关闭”。
标准允许收到 421 的客户端使用不同连接重试,但诊断时仍需明确请求性质。付款、发帖或其他提交失败,应先检查业务是否完成,不把刷新按钮当作无条件重试工具。
3. 有条件地比较 HTTP 版本
Windows 可先运行 curl.exe --version。只有输出的 Features 包含 HTTP2 时,再做下面的两轮测试。选择一个无需登录的普通 HTTPS GET 页面,并确认 curl 与浏览器采用可比较的代理路径;命令行接入问题可参考终端代理排查。
$testUrl = Read-Host '输入要核对的普通 HTTPS 页面 URL'
foreach ($protocolOption in @('--http1.1', '--http2')) {
curl.exe -q --silent --show-error --connect-timeout 10 --max-time 30 `
$protocolOption --output NUL `
--write-out "option=$protocolOption status=%{response_code} http=%{http_version} connect=%{http_connect}`n" $testUrl
}
参数与输出依据 curl 官方手册:status 是最后传输的响应码,http 是实际使用的 HTTP 版本,connect 是代理 CONNECT 的响应码。没有发起 CONNECT 时,不能把该项当成源站结果。
--http2 对 HTTPS 是发起协商,不保证最终使用 HTTP/2,必须看 http。两次 curl 是独立进程、各访问一个 URL,不会重现浏览器跨域复用的完整历史;它们只提供新连接下的对照。若工具不支持 HTTP/2,记录这一限制即可,不要把参数报错当成网站 421。
4. 根据差异决定交给谁继续查
| 观察结果 | 可继续调查的方向 |
|---|---|
| 浏览器出错,新连接恢复 | 原连接状态、复用与入口配置;尚不能确定根因 |
| 确认 h2 返回 421,HTTP/1.1 正常 | 虚拟主机、TLS 配置及协议相关处理 |
| 两种版本均返回 421 | URL、入口及服务端映射,不局限于 HTTP/2 |
| 仅某条代理路径异常 | 对照实际出站、解析与所到入口,不能只归因于节点 |
以上是线索,不是单项判定。一次最终 200 也不足以证明之前没有出现过 421,客户端可能进行过恢复处理。
站长需要核对哪些配置?
有服务端权限时,应沿“TLS 入口 → 虚拟主机 → 反向代理 → 后端”核对预期映射,确认请求的 scheme、authority 与握手上下文是否被正确处理,并把日志时间与失败请求对应起来。涉及共享证书的多站点部署,可优先检查前述实现文档中的 TLS 一致性要求。
普通读者无需为了访问一个网站修改这些服务端配置。提供一份可复现记录,通常比长期关闭 HTTP/2 或反复更换节点更有帮助。
| 时间/请求方法/目标主机 | 原路径与协议 | 新连接结果 | 对照协议与结果 | 已脱敏错误或请求标识 |
|---|---|---|---|---|
| 待填写 | 待填写 | 待填写 | 待填写 | 待填写 |
资料核对日期:2026-10-30。本文未实测特定服务,示例不关闭证书验证;排查结论以实际响应、连接条件和对应日志为准。
评论