仅当浏览器支持 SNI 时才重定向到 SSL

仅当浏览器支持 SNI 时才重定向到 SSL

我有带有 mod_ssl 的 Apache 2.2 和一堆使用 VirtualHosting 在相同 IP/端口上使用 HTTPS 的站点,因此客户端必须支持 SNI 才能连接到这些虚拟主机。

我想按以下方式配置我的服务器:

当用户输入www.dummysite.com时,他的浏览器支持SNI(服务器名称指示),任何 HTTP 请求都会重定向到https://发送 HSTS 标头的位置。但如果浏览器不支持SNI 则请求由 HTTP 提供服务。

上述规则,按原样表述,实际上是针对那些仍然运行旧版浏览器的用户的后备规则,因为 Mozilla 和 Chrome 没有这个问题,只是为了避免将这些用户排除在网站之外。

我想在 Apache 配置级别执行此重定向,也许使用用户代理上的过滤器。除了确保不存在直接 http:// 引用(否则它们会暗示安全警告)之外,我不想触碰正在运行的应用程序

[编辑](编辑问题时我忘记了问题):要重定向的启用 SNI 的用户代理列表是什么?

答案1

由于 SNI 发生在 SSL/TLS 握手期间,因此当客户端连接到 HTTP 时无法检测浏览器支持。

所以,你是对的;用户代理过滤器是实现此目的的唯一方法。

最大的问题是,您是要对那些您知道不会监听 SNI 的浏览器使用黑名单,还是对那些已知支持 SNI 的浏览器使用白名单。不知名或新设备无法使用该网站似乎是个大问题,所以我认为白名单可能是更好的选择。

在您的 HTTP 中<VirtualHost>

# Internet Explorer 7, 8, 9, on Vista or newer
RewriteCond %{HTTP_USER_AGENT} MSIE\s7.*Windows\sNT\s6 [OR]
RewriteCond %{HTTP_USER_AGENT} MSIE\s8.*Windows\sNT\s6 [OR]
RewriteCond %{HTTP_USER_AGENT} MSIE\s9.*Windows\sNT\s6 [OR]
# Chrome on Windows, Mac, Linux
RewriteCond %{HTTP_USER_AGENT} Windows\sNT\s6.*Chrome [OR]
RewriteCond %{HTTP_USER_AGENT} Macintosh.*Chrome [OR]
RewriteCond %{HTTP_USER_AGENT} Linux.*Chrome [OR]
# Firefox - we'll just make the assumption that all versions in the wild support:
RewriteCond %{HTTP_USER_AGENT} Gecko.*Firefox
RewriteRule ^/(.*)$ https://ssl.hostname/$1 [R=301]

这里也有黑名单选项 - 请记住,这存在将不使用 SNI 的客户端发送到需要 SNI 的站点的风险,但另一方面,会将 IE 10 等新浏览器的用户发送到正确的位置:

# IE 6
RewriteCond %{HTTP_USER_AGENT} !MSIE\s6
# Windows XP/2003
RewriteCond %{HTTP_USER_AGENT} !Windows\sNT\s5
# etc etc
RewriteRule ^/(.*)$ https://ssl.hostname/$1 [R=301]

有很多浏览器。我对表达式的使用非常随意,没有涵盖很多浏览器 - 这可能会成为维护的噩梦。

无论你选择哪个选项,祝你好运!

答案2

我的解决方案是这样的:

  # 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 的旧浏览器尝试访问https://www.example.com/* 然后它会首先在浏览器上抛出一个错误,这是无法避免的,因为直到 apache 回复非 SNI 浏览器时,它才知道它请求的是哪个网站。然后它会重定向到一个页面,告诉用户他们的浏览器太旧了(只要用户点击继续访问网站)。

对于使用新浏览器的用户,我有

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

这排除了大多数旧浏览器,包括 Vista 上的 MSIE 5-8(9+ 仅为 Vista/7,因此支持 SNI)。它不是 100%(忽略 symbian 等),但应该适用于大多数人。少数人仍然可以选择接受证书错误。

答案3

据我所知,没有一个好的方法可以做到这一点——你可以使用mod_rewrite 规则或类似有条件的基于User-agent标头,但它必须位于非 SSL 虚拟主机上:如果浏览器才不是支持 SNI 并且它转到一个安全的 ( https://) 网站,它将获得老式的 Apache 行为“这是我与该 IP 地址关联的第一个 SSL 证书 - 希望它是您想要的!”——如果这不是浏览器所期望的证书,您将收到有关主机名不匹配的错误消息。

这基本上意味着人们必须点击一个非 SSL 插入页面,该页面会将他们重定向 - 可能会暴露他们在请求中发送的任何数据。这可能是也可能不是一个交易破坏者(你说如果他们不支持 SNI,你无论如何都会将他们发送到非 SSL 网站,所以我认为你不太关心安全性。如果我正在设计一个需要 SSL 作为加密或身份验证层的系统,我会对此更加坚持......)

然而,这些都无法阻止人们将安全站点添加到书签中 - 并且,如果他们使用共享书签服务或将其书签恢复到 Web 浏览器不支持 SNI 的机器上,他们就会回到潜在 SSL 错误的情况。

答案4

适合任何有需要的人。

如果你有多个主机,并希望它们都在 VirtualHosting 中启用 SSL(并且你为每个主机都购买了证书),请尝试新的mod_djechelon_ssl

$ cat /etc/apache2/mod_djechelon_ssl.conf 
RewriteEngine on
# Internet Explorer 7, 8, 9, on Vista or newer
RewriteCond %{HTTP_USER_AGENT} MSIE\s7.*Windows\sNT\s6 [OR]
RewriteCond %{HTTP_USER_AGENT} MSIE\s8.*Windows\sNT\s6 [OR]
RewriteCond %{HTTP_USER_AGENT} MSIE\s9.*Windows\sNT\s6 [OR]
# Chrome on Windows, Mac, Linux
RewriteCond %{HTTP_USER_AGENT} Windows\sNT\s6.*Chrome [OR]
RewriteCond %{HTTP_USER_AGENT} Macintosh.*Chrome [OR]
RewriteCond %{HTTP_USER_AGENT} Linux.*Chrome [OR]
# Firefox - we'll just make the assumption that all versions in the wild support:
RewriteCond %{HTTP_USER_AGENT} Gecko.*Firefox [OR]
#Safari iThing
RewriteCond %{HTTP_USER_AGENT} Mozilla.*iPhone.*Safari [OR]
RewriteCond %{HTTP_USER_AGENT} Mozilla.*iPod.*Safari [OR]
RewriteCond %{HTTP_USER_AGENT} Mozilla.*iPad.*Safari [OR]
RewriteRule ^/(.*)$ https://%{HTTP_HOST}/$1 [R=permanent,L]

用法:

<VirtualHost ip:80>
ServerName www.yourhost.com

Include /path/to/mod_djechelon_ssl.conf

[plain old Apache directives]
</VirtualHost>

<VirtualHost ip:443>
ServerName www.yourhost.com

[SSL-related directives]

[Copy and paste directives from above host]
</VirtualHost>

相关内容