我可以检测到SSL客户端是否不支持服务器名称指示,并在这种情况下提供标准的HTTP网站?

我将需要使用SSL SNI,但不幸的是,从最近的Cloudflare博客post中,只有90%的networking支持它。 我如何(例如,与nginx)检测客户端是否支持SNI并提供/redirect到HTTP版本的网站? 这可能吗? 如何使用SNI不会丢失10%的stream量? 假设我无法将HTTPSstream量redirect到没有有效证书的HTTP,这是正确的,因此这个请求是不可能的?

谢谢。

如果您想从开始提供HTTPS,则必须提供客户端从开始接受的证书。 否则,客户端将不接受SSL连接,您将无法将客户端redirect到其他站点或仅HTTP版本。 这意味着你支持这个案子

  • 或者需要拥有包含所有域的单个证书,以便您可以向非SNI客户提供适当的证书。 但在这种情况下,你根本不需要SNI。
  • 或者您必须安装一些与您的大部分名称不匹配的默authentication书。 在这种情况下,如果客户端接受这个错误的证书,您只能向客户端提供一个不同的页面或redirect它。

如果您不需要从头开始使用HTTPS,也就是说,如果客户端通常首先使用纯HTTP进行连接,那么您可以尝试检测SNI支持,以便稍后redirect客户端。 这可以通过在HTTPS站点中包含一个图像,一些JavaScript或类似的东西来完成,如果加载成功,那么您知道客户端支持SNI或忽略证书错误。

当然,这会让所有人都面临中间人攻击,因为所有中间人必须做的是提供一些不同的证书,或者根本无法使用HTTPS,因为在这种情况下,您将永远不会尝试将连接升级到HTTPS。 此外,这可以用来使它看起来像客户端支持SNI,如果中间人做它。 不仅如此,非SNI客户端也受到这个影响,但是只有SNIfunction的客户端才能被拦截。 所以虽然这在理论上是可能的,但是不build议这样做,因为你可以简单地把所有东西都放在中间,从而使得使用HTTPS模拟的重点。

正如我在StackOverflow上发布的 ,您只能需要之前testingSNI支持。 也就是说,你不能强制用户进入SNI HTTPS,如果他们不支持,就会退后,因为他们会收到这样的错误(从Windows XP上的Chrome),无法继续。

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

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

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

  2. 跨域AJAX(CORS)
    与选项1类似,您可以尝试执行从HTTP页面到HTTPS的跨域AJAX请求,但请注意,CORS 仅支持有限的浏览器 。

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

    我们知道在Windows XP及以下版本的IE,Chrome和Opera的所有版本都不支持SNI。 有关支持的浏览器的完整列表,请参阅CanIUse.com 。