全站HTTPs,没那么简单

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

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

  HSTS

  如果一个网站既提供了 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 连接真正建立之前。更糟糕的是,不少浏览器为了“表现更好”,会想办法绕过这个问题。所以缺少中级证书的情况一直存在,一直不会被发现,而程序调用的速度总是上不去,甚至有一定几率报错(我就遇到过这个诡异的问题)。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/19be119c3088247e4172b95f51064d9e.html