全站HTTPs,没那么简单

“全站 HTTPs”俨然成了目前的热门话题,不少网站都在摩拳擦掌要实行全站 HTTPs。凑巧,咱们(沪江)也在推行这个计划。

  一开始你们想得都很简单,把证书购买了、配好了,相应的路径改一改,就没有问题。事实也确实如此,单个独立站点的 HTTPs 改造是很容易的。一旦走向“全站”,才发现事情远远比想象的要复杂,全站意味着全部资源面对全部客户端,涉及的因素异常多,网络上又没有太多资料,只能本身摸索。下面我简单讲讲遇到的几个问题,提供一些经验给你们参考。css

  HSTSlinux

  若是一个网站既提供了 HTTP 服务,又提供了 HTTPs 服务(在过渡期一般如此),怎样引导用户访问 HTTPs 的站点呢?这就是 HSTS(HTTP Strict Transport Security)的做用。经过 Web 服务器上的设置,在收到 HTTP 访问请求时,返回的 header 里带有 Strict-Transport-Security 字段,告知浏览器必须使用 HTTPs 进行访问。浏览器

  可是,HSTS 并不能避免首次跳转时遇到的劫持。要完全解决这个问题,能够申请加入 Preload List(预加载列表)。安全

  Preload List 是由 Google Chrome 维护的“HTTPs 站点列表”,Chrome, Firefox, Safari, Edge, IE 11 均在使用。一旦浏览器发现要访问的站点在 Preload List 上,默认就会发起 HTTPs 连接。这样,就避免了 HSTS 的首次跳转被劫持的隐患。服务器

  SSL 卸载网络

  一般的方案里,HTTPs 的加密传输只限于客户端出发的公网阶段,在内网的通信流量仍然采用非加密的 HTTP 传输。这种“把加密流量转换为非加密流量”的过程,就是常说的 SSL/TLS 卸载(Offloading,如下简称“SSL 卸载”)。并发

  有一些公司会采用 F5 来作负载均衡,F5 应付单纯的 L4 和 L7 的流量是没有问题的,但进行 SSL 卸载时性能每每会急剧下降,F5 能够提供专门的加速卡来解决这个问题,但价格不便宜。因此,还须要专门环节来进行 SSL 卸载,常见的 Nginx 和 HAProxy 均可以执行这个任务。负载均衡

  2010 年 Intel 出品的 Westmere 系列处理器以后,CPU 支持 AES-NI (Advanced Encryption Standard New Instructions)指令集,能够极大提升软件进行 SSL 加解密的速度(一般的数据是 5 倍左右)。可是,单纯采用 CPU 并不会直接享受这种好处,还须要对应的 OpenSSL 提供支持。想要知道本身的 OpenSSL 是否利用了 AES-NI 加速,能够用 OpenSSL 的命令行调试,加上-evp 参数,测试速度是否有明显变化便可。工具

# without EVP API性能

openssl speed aes-256-cbc 

Doing aes-256 cbc for 3s on 16 size blocks: 14388425 aes-256 cbc's in 3.00s

# with EVP API

openssl speed -evp AES256

Doing aes-256-cbc for 3s on 16 size blocks: 71299827 aes-256-cbc's in 3.00s

  客户端证书

  HTTP 的服务是很好验证的。通常来讲,不管客户端是浏览器,仍是其它工具,仍是程序代码,一样的行为,结果都是相同的。因此只要一种客户端验证经过,基本就能够认为这个服务是没有问题的。HTTPs 的站点则不是如此。

  与 HTTP 不一样,HTTPs 的链接创建是须要进行证书验证的,必定要从根证书开始造成完整的信任链条,链接才能够创建成功。然而,浏览器、普通工具、程序类库,它们所信任的根证书在管理上是互相独立的。好比,与浏览器不一样的是,C#信任的根证书在 local machine store 或者 current user store 中,Java 信任的根证书在 JDK 安装目录下的 cacerts 目录中。

  由于浏览器的证书在使用中又能够持续更新,用户每每感知不到,若是“想固然”认为浏览器验证经过就万事大吉,极可能会出问题。好比国内有很多网站使用 WoSign 签发的证书,但老版本的 JDK 并步信任 WoSign 的根证书,用浏览器浏览没问题的网站,程序就会报错,除非手动导入证书。由于 WoSign 行为不端,前几天 Firefox, Chrome, Safari 等主流浏览器又取消了对它的信任,也就意味着 WoSign 证书有安全风险,因此已经内置 WoSign 根证书的程序也应当作对应的设置。

  服务器端证书

  仍是上面的现象:用浏览器验证没有问题的 HTTPs 站点,用程序访问就有问题。这是为何?

  在服务器上证书配置错误,只有最终证书,而缺乏中级证书的状况,我见过几回了。一般,最终证书里包含了中级证书相关的信息,因此若是缺乏中级证书,浏览器为了创建证书链,会作一次耗时的操做来获取中级证书,并且这一切都发生在 HTTPs 链接真正创建以前。更糟糕的是,很多浏览器为了“表现更好”,会想办法绕过这个问题。因此缺乏中级证书的状况一直存在,一直不会被发现,而程序调用的速度老是上不去,甚至有必定概率报错(我就遇到过这个诡异的问题)。

  若是把证书链配置彻底,还要注意证书链的大小。有一些网站的完整证书异乎寻常地大,达到若干 kb 甚至几十 kb,也就是说,在创建链接以前,就必须先传输这么多的数据。若是作单纯的 PC 网页浏览,或许不会有问题。但对于移动端和程序调用来讲,这就是一场灾难。最好的办法,是用 OpenSSL 配合 WireShark 之类的工具,本身动手来测试。若是你熟悉 TCP 相关的知识,每每能够获得更好的优化方案。

  OCSP 和 CRL 也不可忽略。这两项技术用来保证撤回证书(让证书失效)的有效性。若是你仔细观察,会发现证书里都指定了对应的 OCSP 或者 CRL 的 URL,用来检查证书是否失效。按道理说,在每次创建 HTTPs 链接时,都应当进行 OCSP 或 CRL 检查。返回结果一般在 1k 左右,若是请求很是频繁,这个因素也应当考虑。

  SNI

  你们都熟悉“虚拟主机”的概念,它可让多个域名对应到同一个 IP,让同一台服务器服务多个站点。在 HTTP 时代,能够在 header 中经过 host 来指定须要访问的域名,一切看起来都那么完美。

  可是在 HTTPs 时代,却没有这样的好事,传统的 HTTPs 服务很难让多个域名对应到同一个 IP。在进行到 HTTP 通信以前,必须先创建验证证书创建链接。若是一个 IP 上绑定了多个域名,这个阶段服务器根本无法知道请求对应的是哪一个域名,无疑会形成极大的不便。

  为了解决这种问题,SNI (Server Name Identification)应运而生了。这种技术提及来复杂,你们能够把它简单理解为“创建 SSL/TLS 通信时的 host header”,这样就解决了一个 IP 只能配单张证书的问题。

  然而 SNI 的诞生历史并不长,许多客户端的支持都存在奇怪的问题。好比 JDK7 支持 SNI,可是 JDK8 的支持又有 bug。并且这种支持每每须要调用原生的 API 才能够实现,Resteasy 之类的类库并不支持。若是对 SNI 的支持有问题,即使配置正确也可能没法创建链接,由于服务端并不能识别此请求须要的证书。

  CDN

  CDN 已是业界流行的技术了,对稍微大一点的网站来讲,没有 CDN 几乎是不可想象的。HTTP 时代的 CDN 方案至关成熟,HTTPs 的状况则不是如此。

  要使用 HTTPs 的 CDN 服务,就要决定是否将证书交给 CDN 提供商。基于中国目前的商业信誉水平,把证书交给 CDN 提供商的风险不可步考虑。恶意揣测,别有用心的人一旦拿到证书,能够很方便地经过 DNS 劫持发起中间人攻击,而彻底不被感知到。

  另外,HTTP 时代你们都喜欢将资源分散到多个不一样的域名,由于创建链接的成本很低,而同一个域名的并发链接数有限。在 HTTPs 环境下,每次创建链接的成本高了不少,频繁下载和验证证书对移动设备和移动网络影响很大(尤为是证书很大的状况)。若是域名很是分散,影响就更加显著。因此在 HTTPs 时代,把域名收缩集中反而是更好的办法。

  内容及其它

  由于 HTTPs 的内容中没法引用 HTTP 的资源,因此应当保证网页中资源文件的连接都是 HTTPs 的。遗留的许多系统极可能并不注意这些事情,资源都采用绝对地址的形式,这样改起来工做量很大。若是要修改,最好一步到位,直接改为“协议相对 URL”。

  绝对地址 URL:http://www.a.com/b.css

  协议相对 URL://www.a.com/b.css

  这样浏览器就能够根据当前的协议,自动生成资源的绝对地址,不管是 HTTP 仍是 HTTPs,均可以自由切换。

  若是资源都是自有的,切换 HTTPs 就相对容易。若是存在外部,尤为是 UGC 的资源,切换到 HTTPs 就很麻烦。若是是超连接,一般采用专门的跳转服务,也就是下面这样:

  https://link.my.com/target=www.you.com

  若是是图片这类资源,能够设定专门的程序将其抓取过来存放在本身的服务器上,再将地址替换掉便可。可是,这样作极可能要本身承担流量压力,同时还要承担恶意程序攻击的风险。

  若是是视频、游戏等富文本、交互复杂的资源,若是源站没有提供 HTTPs 的服务,多半只能忍痛割爱,放弃内嵌展示的形式了。

  最后再补充两点经验:

  1. 若是真的决定上 HTTPs,最好有我的把 OpenSSL 玩熟,不然不少问题会让你摸不着头脑,OpenSSL 是很好的调试工具,很方便定位问题。

  2. HTTPs 能解决运营商内容劫持的问题,若是是 DNS 劫持,要不要抱着“吾与汝偕亡”的态度上 HTTPs,须要慎重考虑,我知道很多网站是 HTTP 与 HTTPs 能够随时切换的,进可攻,退可守。

本文永久更新连接地址http://www.linuxidc.com/Linux/2016-11/137212.htm

相关文章
相关标签/搜索