HTTPS握手
从一份nginx配置谈起
|
ssl_protocols
当前流行的https加密协议包括SSL3.0 TLS1.0 TLS2.0 TLS3.0
TLS(Transport Layer Security 传输层安全协议)是SSL(Secure Sockets Layer 安全套接字)的替换协议。目前协议状态如下协议 发布时间 状态 SSL 1.0 未发布 安全问题未发布 SSL 2.0 1995年 已于2011年弃用 SSL 3.0 1996年 已于2015年弃用 TLS 1.0 1999年 计划于2020年弃用 TLS 1.1 2006年 计划于2020年弃用 TLS 1.2 1999年 主流协议 TLS 1.3 2008年 主流浏览器已经支持 HTTPS 加密流程采用那种协议需要客户端与服务器协商,考虑到客户端版本滞后的特性,服务器必须支持多种协议,比如上面这份nginx的配置来自Mozilla建议支持TLS1.2、TLS1.3。
Mozilla 这份配置的兼容性 Firefox 27, Android 4.4.2, Chrome 31, Edge, IE 11 on Windows 7, Java 8u31, OpenSSL 1.0.1, Opera 20, and Safari 9
从上面我们已知的HTTPS加密支持TLS、SSL,那么这两种协议差异在哪里?我们该如何选择呢?TLS 握手
对于现代短连接服务端设置一般来说支持TLS1.2 TLS1.3 没有任何问题,探究细节客户端与服务端怎么选择使用那个版本的协议呢?
这个流程为TLS握手的大致过程,早期的SSL握手过程也差不多,只是更简单点。[图片来自cloudfare]
参照真实测试了解一下TLS通信过程
➜ ~ curl -I -v https://notes.icool.io
* Trying 47.240.72.238...
* TCP_NODELAY set
* Connected to notes.icool.io (47.240.72.238) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=notes.icool.io
* start date: Dec 23 08:24:36 2019 GMT
* expire date: Mar 22 08:24:36 2020 GMT
* subjectAltName: host "notes.icool.io" matched cert's "notes.icool.io"
* issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after过程解析(TLS1.2为例)
1.密钥交换和密钥协商(1)
- 客户端发送 ClientHello
客户端随机数(会话密钥); S1.0 TLS1.1 TLS 1.2;加密套件,比如 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-GCM-SHA256; 压缩算法;SessionId (会话恢复时使用)
- 服务端发送 ServerHello 到客户端(2)
服务端随机数;服务端选定的协议版本; 加密方法
2.服务端发送证书(11)
客户端收到证书会使用系统预存CA证书校验证书合法性、过期时间、证书状态等信息
3.服务端发送公钥交换(12)
服务器公钥; 签名(使用RSA私钥签名)
4.服务端握手完成(14)
5.客户端公钥交换(16)
#客户端生成主密钥,使用公钥加密后发送服务端
master_secret = PRF(pre_master_secret, "master secret",ClientHello.random + ServerHello.random)
6.握手完成以本次握手为例,稍后通信将使用AES256作为对称加密算法,主密钥做密钥加密通信
- 客户端发送 ClientHello
ssl_ciphers
不同服务器加密套件选择,建议使用Mozilla建议,
https://ssl-config.mozilla.org/#server=nginx&version=1.17.7&config=intermediate&openssl=1.1.1d&guideline=5.4HSTS( HTTP严格传输安全)
HSTS可以用来抵御SSL剥离攻击,要求浏览器总是使用https访问网站。
OCSP
握手阶段我们提到了,客户端获取证书后需要使用预制的CA校验证书,但这里存在一定风险 – 证书吊销,服务器通过配置ssl_stapling=on通知浏览器做证书在线验证。