421 错误请求

421 错误请求

我偶尔会收到以下 421 错误:

错误请求

客户端需要为该请求建立新连接,因为请求的主机名与用于此连接的服务器名称指示 (SNI) 不匹配。

但是,刷新浏览器会清除错误,页面会正常加载。下次加载页面时不会产生错误,因此模式似乎非常随机。我能看到的唯一模式是,当我使用 header("Location: " . $url); 重定向页面时,可能会发生这种情况;

我有 Comodo 的 PositiveSSL 多域证书。我的服务器是共享网络托管服务上的 Apache,因此我无法访问配置。

我从一个域加载页面,并且页面内有指向证书上的第二个域的链接。

我读过的有关此错误的所有内容似乎都指出此问题与多域证书有关。

我想知道的是,网页(php)编码方面是否存在任何问题会导致这种情况(并可以修复),或者是否是配置错误或可能是服务器错误,并且只有我的托管服务可以修复它。

我的托管服务到目前为止无法提供任何帮助,并要求下次回电告知确切时间,以便他们进行研究。任何帮助我都会很感激,因为我不太相信他们能解决这个问题。

更新 好吧,差不多过了几年,我决定是时候解决这个问题了。我通过删除提供图片和 JavaScript 的静态域解决了大部分问题。但是,我仍然使用第二个域来处理其中一些内容,尤其是 Safari 仍然给我带来问题。

我做了更多的研究,发现了另一篇文章在这里谈论它。与@Kevin 描述的完全一样。文章证实了这种情况发生在 Safari 中。因此,我采纳了建议,着手为每个域获取单独的证书。我使用共享主机 (Webhostinghub),发现他们现在提供自动续订的免费 SSL (AutoSSL)。这听起来好得令人难以置信。他们为我设置了 5 个免费证书。到目前为止一切顺利。我甚至可能会尝试重新启用静态域进行测试。如果这一切都有效,我将节省 $ 作为奖励,并让我的 Comodo 证书在 7 月到期。

答案1

这是由以下一系列事件引起的:

  1. 服务器和客户端都支持并使用HTTP/2。
  2. 客户端请求位于 的页面foo.example.com
  3. 在 TLS 协商期间,服务器会提供对foo.example.com和均有效的证书bar.example.com(并且客户端会接受该证书)。这可以使用通配符证书或 SAN 证书来完成。
  4. 客户端重新使用该连接来发出请求bar.example.com
  5. 服务器无法或不愿意支持跨域连接重用(例如因为你以不同的方式配置了他们的 SSL并且 Apache 想要强制进行 TLS 重新协商),并提供 HTTP 421。
  6. 客户端不会自动重试新的连接(例如Chrome 错误 #546991,现已修复)。相关 RfC表示客户端可以重试,而不是应该或必须重试。重试失败对用户来说不是特别友好,但对于调试工具或 HTTP 库来说可能是理想的选择。

事件 #6 不受您的控制,但根据服务器的软件,事件 #5 可能是可以修复的。有关服务器如何以及何时发送 HTTP 421 的更多信息,请参阅服务器的 HTTP/2 文档。或者,您可以为每个域颁发单独的证书,但这会增加更多的管理开销,可能不值得。您也可以完全关闭 HTTP/2,但在大多数情况下这可能有点过头了。

答案2

也许这对某些人有帮助。

当我尝试将 Apache 虚拟主机配置更改为 HTTPS 但仅将端口从 80 更改为 443 并忘记添加时,出现了此错误

   SSLEngine on
   SSLCertificateFile "/opt/lampp/htdocs/localhost.crt"
   SSLCertificateKeyFile "/opt/lampp/htdocs/localhost.key"

导致错误421的配置:

<VirtualHost mydoamin.local:443>   <-- fistly I 
       DocumentRoot "/opt/lampp/htdocs/mydomain/"
       ServerName www.mydomain.local
</VirtualHost>

正确的配置:

<VirtualHost mydoamin.local:443>
       DocumentRoot "/opt/lampp/htdocs/mydomain/"
       ServerName www.mydomain.local
       SSLEngine on
       SSLCertificateFile "/opt/lampp/htdocs/localhost.crt"
       SSLCertificateKeyFile "/opt/lampp/htdocs/localhost.key"
</VirtualHost>

答案3

我们在一些使用带有 Apache 的 Debian 10 的网站上观察到 Safari(桌面版和 iPhone)存在同样的问题。

软件:

  • Debian 10
  • Apache2 2.4.38-3+deb10u3 带有 HTTP/2
  • 带有 php-fpm 的 PHP 7.3.14-1~deb10u1

域:

  • www.example.com
  • a.example.com
  • b.example.com
  • 所有域名都指向同一个 DocumentRoot

证书:

解决方案很简单,但花了不少功夫才找到。最后只能不断尝试。

导致错误421的配置:

    # in /etc/apache2/site-enabled/www.example.com.conf
    SSLCertificateFile      /etc/apache2/ssl/www.example.com/cert-123.pem
    SSLCertificateKeyFile   /etc/apache2/ssl/www.example.com/www.example.com.key

    # in /etc/apache2/site-enabled/a.example.com.conf
    SSLCertificateFile      /etc/apache2/ssl/a.example.com/cert-123.pem
    SSLCertificateKeyFile   /etc/apache2/ssl/a.example.com/www.example.com.key

    # in /etc/apache2/site-enabled/b.example.com.conf
    SSLCertificateFile      /etc/apache2/ssl/b.example.com/cert-123.pem
    SSLCertificateKeyFile   /etc/apache2/ssl/b.example.com/www.example.com.key

工作配置:

    # in /etc/apache2/site-enabled/www.example.com.conf
    SSLCertificateFile      /etc/apache2/ssl/www.example.com/cert-123.pem
    SSLCertificateKeyFile   /etc/apache2/ssl/www.example.com/www.example.com.key

    # in /etc/apache2/site-enabled/a.example.com.conf
    SSLCertificateFile      /etc/apache2/ssl/www.example.com/cert-123.pem
    SSLCertificateKeyFile   /etc/apache2/ssl/www.example.com/www.example.com.key

    # in /etc/apache2/site-enabled/b.example.com.conf
    SSLCertificateFile      /etc/apache2/ssl/www.example.com/cert-123.pem
    SSLCertificateKeyFile   /etc/apache2/ssl/www.example.com/www.example.com.key

解决方案(在我们的例子中):不允许将相同的证书和私钥复制到不同的位置!

在我们将证书复制到 VirtualHost 特定目录之前。这会导致错误请求仅适用于 Safari 的行为。

不幸的是,我无法向您解释为什么 :-( (Apache2 错误?Safari 错误?Safari 功能?)

答案4

我遇到了同样的问题,问题出在服务器名称上,它是错误的

错误配置:

<VirtualHost domain.name:443>

    ServerName domain.name2 # SERVER NAME NOT IDENTICAL TO VIRTUALHOST 
    DocumentRoot "/documents/"
    SSLEngine on
    SSLCertificateFile "/etc/apache2/ssl/domain.name.crt"
    SSLCertificateKeyFile "/etc/apache2/ssl/domain.name.key"
    
</VirtualHost>

服务器名称值必须与虚拟主机

当我改为:

<VirtualHost domain.name:443>

    ServerName domain.name
    DocumentRoot "/documents/"
    SSLEngine on
    SSLCertificateFile "/etc/apache2/ssl/domain.name.crt"
    SSLCertificateKeyFile "/etc/apache2/ssl/domain.name.key"

</VirtualHost>

一切顺利,希望有所帮助。

相关内容