关于启用 HTTPS 的一些经验分享(二)

转载: 关于启用 HTTPS 的一些经验分享(二)

几天前,一位朋友问我:都说推荐用 Qualys SSL Labs 这个工具测试 SSL 安全性,为什么有些安全实力很强的大厂家评分也很低?我认为这个问题应该从两方面来看:1)国内用户终端情况复杂,很多时候降低 SSL 安全配置是为了兼容更多用户;2)确实有一些大厂家的 SSL 配置很不专业,尤其是配置了一些明显不该使用的 CipherSuite。

我之前写的《关于启用 HTTPS 的一些经验分享(一)》,主要介绍 HTTPS 如何与一些新出的安全规范配合使用,面向的是现代浏览器。而今天这篇文章,更多的是介绍启用 HTTPS 过程中在老旧浏览器下可能遇到的问题,以及如何取舍。

SSL 版本选择

TLS(Transport Layer Security,传输层安全)的前身是 SSL(Secure Sockets Layer,安全套接字层),它最初的几个版本(SSL 1.0、SSL 2.0、SSL 3.0)由网景公司开发,从 3.1 开始被 IETF 标准化并改名,发展至今已经有 TLS 1.0、TLS 1.1、TLS 1.2 三个版本。TLS 1.3 改动会比较大,目前还在草案阶段。

SSL 1.0 从未公开过,而 SSL 2.0 和 SSL 3.0 都存在安全问题,不推荐使用。Nginx 从 1.9.1 开始默认只支持 TLS 的三个版本,以下是 Nginx 官方文档中对 ssl_protocols 配置的说明:

Syntax: ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];
Default: ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
Context: http, server
Enables the specified protocols. The TLSv1.1 and TLSv1.2 parameters work only when the OpenSSL library of version 1.0.1 or higher is used.

但不幸的是,IE 6 默认只支持 SSLv2 和 SSLv3(来源),也就是说 HTTPS 网站要支持 IE 6,就必须启用 SSLv3。仅这一项就会导致 SSL Labs 给出的评分降为 C。

加密套件选择

加密套件(CipherSuite),是在 SSL 握手中需要协商的很重要的一个参数。客户端会在 Client Hello 中带上它所支持的 CipherSuite 列表,服务端会从中选定一个并通过 Server Hello 返回。如果客户端支持的 CipherSuite 列表与服务端配置的 CipherSuite 列表没有交集,会导致无法完成协商,握手失败。

CipherSuite 包含多种技术,例如认证算法(Authentication)、加密算法(Encryption)、消息认证码算法(Message Authentication Code,简称为 MAC)、密钥交换算法(Key Exchange)和密钥衍生算法(Key Derivation Function)。

SSL 的 CipherSuite 协商机制具有良好的扩展性,每个 CipherSuite 都需要在 IANA 注册,并被分配两个字节的标志。全部 CipherSuite 可以在 IANA 的 TLS Cipher Suite Registry 页面查看。

OpenSSL 库支持的全部 CipherSuite 可以通过以下命令查看:

openssl ciphers -V | column -t
0xCC,0x14 - ECDHE-ECDSA-CHACHA20-POLY1305 TLSv1.2 Kx=ECDH Au=ECDSA Enc=ChaCha20-Poly1305 Mac=AEAD
... ...

0xCC,0x14 是 CipherSuite 的编号,在 SSL 握手中会用到。ECDHE-ECDSA-CHACHA20-POLY1305 是它的名称,之后几部分分别表示:用于 TLSv1.2,使用 ECDH 做密钥交换,使用 ECDSA 做认证,使用 ChaCha20-Poly1305 做对称加密,由于 ChaCha20-Poly1305 是一种 AEAD 模式,不需要 MAC 算法,所以 MAC 列显示为 AEAD。

要了解 CipherSuite 的更多内容,可以阅读这篇长文《TLS 协议分析 与 现代加密通信协议设计》。总之,在配置 CipherSuite 时,请务必参考权威文档,如:Mozilla 的推荐配置CloudFlare 使用的配置

以上 Mozilla 文档中的「Old backward compatibility」配置,以及 CloudFlare 的配置,都可以很好的兼容老旧浏览器,包括 Windows XP / IE6。

之前见到某个大厂家居然支持包含 EXPORT 的 CipherSuite,这些套件在上世纪由于美国出口限制而被弱化过,已被攻破,实在没有理由再使用。

SNI 扩展

我们知道,在 Nginx 中可以通过指定不同的 server_name 来配置多个站点。HTTP/1.1 协议请求头中的 Host 字段可以标识出当前请求属于哪个站点。但是对于 HTTPS 网站来说,要想发送 HTTP 数据,必须等待 SSL 握手完成,而在握手阶段服务端就必须提供网站证书。对于在同一个 IP 部署不同 HTTPS 站点,并且还使用了不同证书的情况下,服务端怎么知道该发送哪个证书?

Server Name Indication,简称为 SNI,是 TLS 的一个扩展,为解决这个问题应运而生。有了 SNI,服务端可以通过 Client Hello 中的 SNI 扩展拿到用户要访问网站的 Server Name,进而发送与之匹配的证书,顺利完成 SSL 握手。

Nginx 在很早之前就支持了 SNI,可以通过 nginx -V 来验证。以下是我的验证结果:

./nginx -V
nginx version: nginx/1.9.9
built by gcc 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04)
built with OpenSSL 1.0.2e-dev xx ‍ xxxx
TLS SNI support enabled
configure arguments: --with-openssl=../openssl --with-http_ssl_module --with-http_v2_module

然而,并不是所有浏览器都支持 SNI,以下是常见浏览器支持 SNI 的最低版本:

阿莫斯论Amos

posted @ 2016-05-16 19:00  Andrew.Zhou  阅读(2808)  评论(0编辑  收藏  举报