【发布时间】:2012-07-26 22:59:48
【问题描述】:
我希望能够检测浏览器是否支持SNI - Server Name Indication。我希望将不合规的客户重定向到不同的地址。
我正在考虑通过 SSL 加载一些内容并确保其安全传输。否则浏览器不支持 SNI。这可以做到吗?
【问题讨论】:
标签: javascript ssl ssl-certificate
我希望能够检测浏览器是否支持SNI - Server Name Indication。我希望将不合规的客户重定向到不同的地址。
我正在考虑通过 SSL 加载一些内容并确保其安全传输。否则浏览器不支持 SNI。这可以做到吗?
【问题讨论】:
标签: javascript ssl ssl-certificate
您可以设置一个支持 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。
【讨论】:
不确定这是不是想要的,但有这个
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}。这段代码可以改进,但你明白了。
【讨论】:
SSL_TLS_SNI 变量的重定向不会起作用。
您只能在需要它之前测试 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。
嗅探用户代理
这可能是最不可靠的方法,您需要在已知不支持它的浏览器(和操作系统)黑名单和支持它的已知系统白名单之间做出决定。
我们知道 Windows XP 及以下所有版本的 IE、Chrome 和 Opera 都不支持 SNI。见CanIUse.com for full list of supported browsers。
【讨论】:
自从 commercerack 为所有网站升级到 SNI 后,我们遇到了同样的问题。 (用户开始结帐并遇到令人讨厌的 SSL 问题)。
请随意将此作为起点。 随着浏览器列表的增长,我会更新,但它现在支持 XP + Android 2.0-2.2 上的 IE。
https://github.com/brianhorakh/html-sni-useragent-sniffer-warning
【讨论】: