【问题标题】:How to simulate non-SNI browsers (without SNI support)?如何模拟非 SNI 浏览器(不支持 SNI)?
【发布时间】:2015-02-03 10:05:05
【问题描述】:

我正在为 Apache 设置几个不同的 SSL 证书,这些证书用于驻留在同一服务器上的不同域(因此共享相同的 IP 地址)。

使用Qualys SSL Test,我发现有些客户端(即BingBot as of december 2013)不支持SNI 扩展。

所以我正在考虑制作一个可以收集此类客户端请求的特殊默认 Web 应用程序,但我如何模拟这些客户端?

我在 Windows 8 上,无法访问 Linux 机器,如果这很重要的话。

【问题讨论】:

    标签: ssl client sni


    【解决方案1】:

    您可以使用最常用的 SSL 库 OpenSSL。 Windows 二进制文件可供下载。

    openssl s_client -connect domain.com:443 命令非常适合从客户端测试 SSL 连接。默认不支持 SNI。您可以附加 -servername domain.com 参数以启用 SNI。

    【讨论】:

    • 这适用于 openssl 版本 1.1.0* 及更早版本。在 1.1.1* 版本中,s_client 默认发送“server_name”扩展名(使用“-connect”参数中指定的任何主机)。如果您不想在较新版本中发送“server_name”,则必须使用“-noservername”将其关闭。
    【解决方案2】:

    如果您使用的是 OpenSSL 1.1.0 或更早版本,请使用openssl s_client -connect $ip:$port,OpenSSL 不会启用 SNI 扩展

    如果您使用的是 OpenSSL 1.1.1,则需要将 -noservername 标志添加到 openssl s_client。

    【讨论】:

      【解决方案3】:

      类似openssl的s_client是gnutls-cli

      gnutls-cli --disable-sni www.google.com
      

      【讨论】:

        【解决方案4】:

        你可以安装Strawberry Perl,然后使用下面的脚本来模拟一个不支持SNI的客户端:

        use strict;
        use warnings;
        use LWP::UserAgent;
        
        my $ua = LWP::UserAgent->new(ssl_opts => {
            # this disables SNI
            SSL_hostname => '', 
            # These disable certificate verification, so that we get a connection even
            # if the certificate does not match the requested host or is invalid.
            # Do not use in production code !!!
            SSL_verify_mode => 0,
            verify_hostname => 0,
        });
        
        # request some data
        my $res = $ua->get('https://example.com');
        
        # show headers
        # pseudo header Client-SSL-Cert-Subject gives information about the
        # peers certificate
        print $res->headers_as_string;
        
        # show response including header
        # print $res->as_string;
        

        通过将 SSL_hostname 设置为空字符串,您可以禁用 SNI,禁用此行会再次启用 SNI。

        【讨论】:

          【解决方案5】:

          使用特殊的默认 Web 应用程序的方法根本行不通。

          您不能这样做,因为所述受限客户端不仅会打开不同的页面,而且会完全失败。

          1. 假设您有一个“默认”虚拟主机,非 SNI 客户端可以正常打开。

          2. 您还有一个额外的虚拟主机,应该由支持 SNI 的客户端打开。

          3. 显然,这两个主机名必须不同(例如,default.example.com 和 www.example.com),否则 Apache 或 nginx 将不知道要显示哪个站点到哪个连接客户端。

          现在,如果非 SNI 客户端尝试打开 https://www.example.com,他将收到来自 default.example.com 的证书,这会给他一个证书错误。这是一个重要的警告。

          解决此错误的方法是制作一个包含www.example.com 和default.example.com 的SAN(多域)证书。然后,如果一个非 SNI 客户端尝试打开https://www.example.com,他将获得一个有效的证书,但即便如此,他的Host: 标头仍将指向www.example.com,并且他的请求将不会被路由到@ 987654330@ 转至www.example.com。

          如您所见,您要么完全阻止非 SNI 客户端,要么将它们转发到预期的虚拟主机。 默认网络应用程序没有明智的选择。

          【讨论】:

          • 投反对票。问题是如何在没有 sni 支持的情况下模拟请求。
          • @Wes 这不公平,因为问题也是关于一个特殊的默认应用程序
          • 我们积极使用默认应用程序,这不会导致问题。其他主机在主题备用名称中。所以你不能这样做是错误的。 (尽管您确实提供了自己的解决方法)它实际上仍然没有回答“但是我如何模拟那些客户”的问题,这既是问题的标题,也是问题中的实际问题。 (抱歉这里很难使用正确的英文)
          • 为什么一个答案应该回答原始问题中的所有问题?有没有法律或规则?
          • 我认为您对此过于认真了。无论如何,目前唯一的问题是如何模拟客户端。我已经删除了 Downvote,但我仍然觉得这些信息有点误导,并且 B 没有回答被问到的唯一问题。实际上我无法删除反对票,我确实尝试过。
          【解决方案6】:

          使用 Java HTTP 客户端,您可以通过设置系统属性 jsse.enableSNIExtension=false 来禁用 SNI 扩展。

          更多:Java TLS: Disable SNI on client handshake

          【讨论】:

            猜你喜欢
            • 2011-11-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-07-06
            • 2011-08-18
            • 2014-01-18
            • 1970-01-01
            相关资源
            最近更新 更多