考虑停用HTTP/2

近期访问本站,经常会出现421 Misdirected request的错误码,究其本源,是由于HTTP/2的某些特性和多域名(多SAN*1)证书冲突造成的.

Google以下这个421错误码+Apache的关键字,找到官方解释:

https://httpd.apache.org/docs/2.4/mod/mod_http2.html

Multiple Hosts and Misdirected Requests

Many sites use the same TLS certificate for multiple virtual hosts. The certificate either has a wildcard name, such as ‘*.example.org’ or carries several alternate names. Browsers using HTTP/2 will recognize that and reuse an already opened connection for such hosts.

While this is great for performance, it comes at a price: such vhosts need more care in their configuration. The problem is that you will have multiple requests for multiple hosts on the same TLS connection. And that makes renegotiation impossible, in face the HTTP/2 standard forbids it.

So, if you have several virtual hosts using the same certificate and want to use HTTP/2 for them, you need to make sure that all vhosts have exactly the same SSL configuration. You need the same protocol, ciphers and settings for client verification.

If you mix things, Apache httpd will detect it and return a special response code, 421 Misdirected Request, to the client.

译:多(虚拟)主机和错误定向的请求(问题)

许多站点为多个虚拟主机(vHost)使用同一个TLS证书。这个证书要么包含通配符,比如”*.example.org”;要么包含多个SAN(译者注:即可用于多个域名)。支持HTTP/2的浏览器会辩认出这点(多个vHost使用相同证书)并为这样的主机复用已建立的(TCP)连接。

这对(提高)性能来说是极好的,但也有代价:这类vHost的配置需要更多的关注。问题在于你对(多个)不同的vHost的不同请求是通过同一个TLS连接所发送的。这将造成无法重协商(renegotiation),而且是HTTP/2标准导致其无法完成(重协商)。

所以,如果你有多个使用相同证书的vHost且打算让它们支持HTTP/2,你需要确保它们具有完全相同的SSL配置——相同的(TLS)协议、相同的加密套件和客户端验证设置(编者注:用于双向验证,一般站点不需要)。

如果有混合(多种)配置,Apache httpd会检测到这种情况并给客户端(浏览器)返回一个特殊的HTTP状态码——421 Misdirected Request

我没有使用多种SSL配置,所有站点的SSL配置(TLS协议、加密套件)均是由mod_ssl的配置文件决定的,不存在『使用同一证书的多站点SSL配置不相同』的情形,但这个421 Misdirected Request就是出现了。

HTTP/2中的TLS会话复用似乎是为了提高性能,而我使用多SAN的证书则是因为要考虑站点对老旧的、不支持SNI*2的浏览器的兼容性。


*1.SAN:Sub Alternate Name,子可选域名.多域名证书会包含多个SAN.
*2.SNI:Server Name Indication,服务器名称指示.支持SNI的浏览器可以在服务器发来多个TLS证书时,找出与所请求域名匹配的证书.

《考虑停用HTTP/2》有6个想法

    1. @wq : 我这边已经解决了,似乎是一个vHost使用了与mod_ssl的配置文件中定义的不同的TLS协议版本和加密套件造成的
      确保……标签之间没有SSLCipherSuiteSSLProtocol就行了

发表评论

电子邮件地址不会被公开。