检测和重定向SNI支持的浏览器的最有效代码是什么?

时间:2014-06-01 10:15:29

标签: .htaccess ssl sni

说,我有一个使用Apache Httpd托管的网站mywebsite.com。现在我想要的是,无论何时任何用户键入mywebsite.comwww.mywebsite.com,如果浏览器支持SNI,那么它应该重定向到https://www.mywebsite.com,否则重定向到http://www.mywebsite.com

那么,实现它的最有效方法是什么?

4 个答案:

答案 0 :(得分:2)

以下代码应该有效

Options -Indexes +FollowSymLinks
RewriteEngine on

RewriteCond %{HTTP_HOST} ^mywebsite.com$
RewriteCond %{HTTPS} (on|off)
RewriteRule ^(.*)$ http://www.mywebsite.com/$1 [R=302,L]

RewriteCond %{HTTPS} off
RewriteCond %{HTTP_USER_AGENT} !MSIE\s6
RewriteCond %{HTTP_USER_AGENT} !Windows\sNT\s5
RewriteCond %{HTTP_USER_AGENT} !^(.*.symbian.*) [NC]
RewriteCond %{HTTP_USER_AGENT} !^(.*.blackberry.*) [NC]
RewriteRule ^(.*)$ https://www.mywebsite.com/$1 [R=302,L]

这里我们忽略了大多数不支持SNI的浏览器,因此只会加载http版本。

答案 1 :(得分:1)

更好的解决方案是

  #Test if new browser and if so redirect to https
  #new browser is not MSIE 5-8, not Android 0-3,
  #not any symbian and not any blackbery
  RewriteCond %{HTTPS} off
  RewriteCond %{HTTP_USER_AGENT} !MSIE\ [5-8] [NC]
  RewriteCond %{HTTP_USER_AGENT} !Android.*(Mobile)?\ [0-3] [NC]
  RewriteCond %{HTTP_USER_AGENT} !^(.*.symbian.*) [NC]
  RewriteCond %{HTTP_USER_AGENT} !^(.*.blackberry.*) [NC]
  RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

这忽略了MSIE 5-8,它排除了XP上的所有IE,加上一些可用的VISTA。但允许XP使用chrome,firefox,opera,所有这些都支持XP上的SNI。这至少允许XP用户使用https。同样,它假设所有的symbian,blackbery都没有sni。而且知识产权3确实如此(据我所知,平板电脑需要4个)。

对于其他解决方案,您可以

  #Could use this to set $_SERVER['SSL_TLS_SNI'] for php
  SetEnv SSL_TLS_SNI %{SSL:SSL_TLS_SNI}

这会将$ _SERVER [' SSL_TLS_SNI']设置为%{SSL:SSL_TLS_SNI}(可能是更好的代码)或域名。如果您知道apache返回的默认证书是什么,并且可以访问该域,那么在其他域中您可以让php对默认域执行测试https,然后检查$ _SERVER [' SSL_TLS_SNI']在进入https之前测试SNI。

注意如果非sni浏览器对需要sni的站点进行https,则无法避免出现错误消息。你能做的最好的就是

  # 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]

用户需要接受浏览器错误并继续访问网站,之后他会被重定向到http和错误页面。

答案 2 :(得分:1)

这是我根据上述答案使用的。

RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=302]

RewriteCond %{HTTP_USER_AGENT} !MSIE\s7
RewriteCond %{HTTP_USER_AGENT} !Windows\sNT\s5
RewriteCond %{HTTP_USER_AGENT} !Android.*(Mobile)?\ [0-3] [NC]
RewriteCond %{HTTP_USER_AGENT} !^(.*.symbian.*) [NC]
RewriteCond %{HTTP_USER_AGENT} !^(.*.blackberry.*) [NC]
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

如果未列出useragent,则首先重写为http,然后重写为https。 我不知道这是不是有两次重写,但我相信谷歌和其他相关的机器人更喜欢索引https。这种方式实现了(我想:):

我的向后做法但它似乎有效。我相信你会更好地将黑名单列入黑名单,并将它们导航到HTTP而不是白名单浏览器,因为要添加的内容太多了。

每个站点都不同,根据安全性,上述可能是一种选择。

请让我知道你的想法。

答案 3 :(得分:0)

您可以设置第二个只能与SNI一起使用的服务器,并使第一个站点上的页面向它发出Ajax请求(如果需要,可能带有一些标识符)。

如果客户端不支持SNI,则服务器将显示所请求主机名的无效证书。因此,Ajax请求不起作用。您可以让初始页面对该失败做出反应,这表明SNI不受支持。

当然,这并不完美,但这可能比依赖明确的用户代理列表(取决于您的约束)更好。这将更直接地测试客户端功能。