我希望能够检测浏览器是否支持SNI - Server Name Indication。我希望将不合规的客户端重定向到不同的地址。
我正在考虑通过SSL加载一些内容并确保它安全地传输。否则浏览器不支持SNI。可以这样做吗?
答案 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支持:
远程脚本
在普通HTTP页面中,从目标SNI HTTPS服务器加载<script>
,如果脚本加载并正确运行,您就知道浏览器支持SNI。
跨域AJAX(CORS)
与选项1类似,您可以尝试从HTTP页面到HTTPS执行跨域AJAX请求,但请注意CORS已only limited browser support。
嗅探用户代理
这可能是最不可靠的方法,您需要决定是否知道不支持它的浏览器(和操作系统)的黑名单,或者已知系统的白名单。
我们知道所有版本的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