在javascript中检测SNI(服务器名称指示)浏览器支持

时间:2012-07-28 14:20:28

标签: javascript ssl ssl-certificate

我希望能够检测浏览器是否支持SNI - Server Name Indication。我希望将不合规的客户端重定向到不同的地址。

我正在考虑通过SSL加载一些内容并确保它安全地传输。否则浏览器不支持SNI。可以这样做吗?

4 个答案:

答案 0 :(得分:4)

你可以设置一个支持SNI的服务器,提供两个主机名,你需要SNI的地方和一个后备解决方案,它们都提供他们所托管的名称。

有些事情:

  • https://www.example.com/name返回表示I'm www.example.com
  • 的表示
  • https://www.example.net/name返回I'm www.example.net(并要求SNI)。

如果您向https://www.example.net/name发出XHR请求并返回www.example.com,则浏览器不支持SNI。

答案 1 :(得分:1)

不确定这是否是想要的但是有这个

  RewriteEngine on

  # Test if SNI will work and if not redirect to too old browser page
  RewriteCond %{HTTPS} on
  RewriteCond %{SSL:SSL_TLS_SNI} =""
  RewriteRule ^ http://www.example.com/too-old-browser [L,R=307]

如果旧浏览器试图使用需要SNI的网站,那么它将被重定向(在这种情况下返回到http和一个说浏览器太旧的页面)。但是你总会得到一个错误。这是无法避免的。浏览器说你好IP ....,apache回复你好,这是我的证书。如果浏览器不在hello apache中提供SNI,则只发送默认(即错误)证书。然后浏览器抱怨。

如果你想在交换到https之前从http中选择这个,那么你可以在htaccess中输入这样的内容

  #Set $_SERVER['SSL_TLS_SNI'] for php = %{SSL:SSL_TLS_SNI} or value
  SetEnv SSL_TLS_SNI %{SSL:SSL_TLS_SNI}

然后在您的页面中从默认域执行https提取(默认情况下,因此浏览器不会说存在安全性错误)。如果SNI正在工作,那么php $ _SERVER ['SSL_TLS_SNI']将拥有域名,否则它将具有%{SSL:SSL_TLS_SNI}。这段代码可以改进,但你明白了。

答案 2 :(得分:1)

您只能在之前测试SNI支持。也就是说,你不能强迫用户使用SNI HTTPS然后如果他们不支持它就会退回,因为他们会收到这样的错误(来自Windows XP上的Chrome),无法继续。

所以(不幸的是)用户必须实际上从一个不安全的HTTP连接开始,然后只有在它们支持SNI时才升级。

您可以通过以下方式检测SNI支持:

  1. 远程脚本
    在普通HTTP页面中,从目标SNI HTTPS服务器加载<script>,如果脚本加载并正确运行,您就知道浏览器支持SNI。

  2. 跨域AJAX(CORS)
    与选项1类似,您可以尝试从HTTP页面到HTTPS执行跨域AJAX请求,但请注意CORS已only limited browser support

  3. 嗅探用户代理
    这可能是最不可靠的方法,您需要决定是否知道不支持它的浏览器(和操作系统)的黑名单,或者已知系统的白名单。

    我们知道所有版本的IE,Chrome&amp; Windows XP及更低版本的Opera不支持SNI。请参阅CanIUse.com for full list of supported browsers

答案 3 :(得分:0)

由于commercerack升级为所有网站的SNI,我们遇到了同样的问题。 (用户开始结账并获得令人讨厌的SSL问题)。

随意将此作为起点。 随着浏览器列表的增长,我将更新,但它现在在XP + Android 2.0-2.2上进行了IE。

https://github.com/brianhorakh/html-sni-useragent-sniffer-warning