HTTPS
HTTPS
HTTPS 全称是 HTTP over SSL,也就是通过 SSL/TLS 加密 HTTP 数据,这或许是 SSL 最广泛的应用。
SSL/TLS 协议简单介绍
参考:吐血整理,HTTPS 看这篇就够了,一次给你说个明白-CSDN 博客,这篇博客里详细介绍了TLS协议,非常值得参考
HTTPS 是身披 SSL/TLS 外壳的 HTTP 协议,它并非一个新的协议而是在 HTTP 的基础上新增了安全层 (SSL/TLS),HTTPS 先和安全层通信,然后安全层和 TCP 层通信。
TSL 位于 TCP 和 HTTP 之间,即在传输层上

TLS 全称传输安全层协议,Transport Layer Security Protocol,TLS/SSL 是一种加密通道的规范。
SSL 全称 Secure Sockets Layer 安全套接字协议
TLS/SSL 的发展历史
版本 | 描述 |
---|---|
SSL 1.0 | 存在严重的安全漏洞,从未公开过 |
SSL 2.0 | 在 1995 年 2 月发布,但是存在数个严重的安全漏洞很快被 3,0 替代 |
SSL 3.0 | 1996 年发布 |
TLS 1.0 | IETF 对 SSL3.0 进行了标准化,并添加了少数机制 但是几乎和 SSL3.0 一样 |
TLS 1.1 | 在 RFC 4346 中定义,2006 年 4 月发布 |
TLS 1.2 | 在 RFC 5246 中定义 2008 年 8 月发布 |
TLS 1.3 | 在 RFC 8446 中定义,于 2018 年 8 发表。 |
TLS 协议是由 TLS 记录协议和 TLS 握手协议叠加而成的 | |
记录协议:TLS Record protocol |
- TLS 记录协议位于 TLS 握手协议的下层,是负责使用对称密码进行加密通信的部分
- 加密使用的秘钥,是通过握手协议在服务端和客户端之间协商决定的
握手协议:TLS Handshaking Protocols - 由 TLS Change Ciper Spec Protocol(密码规格变更协议) 和 TLS ALert Protocol(警告协议) 组成
- 负责在客户端和服务器之间协商决定密码算法和共享秘钥
- 密码规格变动协议负责向通信对象传达变更密码方式的信号,协议中途发生错误时,就会通过警告协议传达给对方。
- 警告协议是 TLS 握手协议负责在发送错误时将错误传达给对方。
由于有了传输安全层 TLS,所以 HTTPS 比 HTTP 的安全性大幅提高
- TLS Record Protocol 保证了数据的隐私性和完整性
- TLS Handshaking Protocols 实现了身份认证。
HTTPS 的通信过程
完整的 HTTPS 的流程图:

其中,跟 HTTP 相比,多出来的中间那一段儿是 TLS/1.2
的握手过程,不过注意,其中只有客户端对服务端的单向验证。

HTTPS (HTTP Secure) 是使用了 SSL/TLS
协议进行加密处理的 HTTP。TCP 握手之后的通信过程大致可以分为两个阶段:SSL/TLS
握手和 HTTP 请求/响应交换。
https 的工作流程详解 - sword0077 - 博客园
吐血整理,HTTPS 看这篇就够了,一次给你说个明白_ssl_ciphers sha1-CSDN 博客 的
完整的HTTPS的通信过程
小节详细介绍了TSL/1.2
的细节
SSL/TLS
握手-
客户端向服务器发起连接请求:客户端发送 "Client Hello" 消息给服务器,包括客户端支持的
SSL/TLS
版本号(TLS Versiion)、一个客户端生成的随机值(Client random)R1、客户端支持的加密方法列表(Cipher Suite)等信息。 -
服务器响应:服务器收到 "Client Hello" 后,选择一个客户端也支持的加密方法(Cipher Suite)和最高版本的
SSL/TLS
协议(TLS Versiion),然后产生一个随机值(Server random)R2,并返回 "Server Hello" 消息给客户端。 -
服务器提供凭证:服务器会向客户端发送其证书(包含服务器的公钥)和 "ServerHello Done" 消息。证书通常由受信任的证书颁发机构(CA)签名。
-
客户端验证证书并生成密钥:客户端验证服务器的证书是否被可信的 CA 签名,确认服务器真正拥有公钥。然后,客户端会生成一个预主密钥(Pre-Master Secret)R3,并使用服务器的公钥进行加密然后发送给服务器。
-
生成会话密钥:服务器使用自己的私钥对预主密钥 R3 进行解密,得到真正的预主密钥 R3。然后,客户端和服务器使用相同的方式,各自同时使用客户端随机值 R1、服务器随机值 R2 和预主密钥 R3 这三个值,生成会话密钥(Session key)。这个会话密钥用于接下来的会话加密。
-
客户端发出握手结束通知:客户端向服务器报告握手结束,并使用会话密钥加密这个消息。到此为止,
SSL/TLS
握手过程结束。
-
- HTTP 请求/响应交换
- 发送请求:
SSL/TLS
握手结束后,客户端就可以开始向服务器发送 HTTPS 请求了。请求中的所有内容,包括 HTTP 头、请求体等,都会使用在SSL/TLS
握手过程中生成的会话密钥进行加密。 - 服务器响应:服务器接收到加密的 HTTPS 请求后,使用会话密钥对其进行解密,然后处理请求并生成响应。然后,服务器使用同样的会话密钥加密 HTTP 响应,并将其发送给客户端。
- 客户端处理服务器响应:客户端收到响应后,使用会话密钥解密 HTTP 响应,然后处理响应。
这个过程确保了整个会话的秘密性和完整性,因为所有的请求和响应都是加密的,防止了中间人攻击和窃听。同时,SSL/TLS
握手过程中的证书验证还提供了服务端的身份验证,保证了你正在与正确的服务器进行通信。
- 发送请求:
HTTPS 默认采用 443 端口,HTTP 协议默认采用 80 端口,注意不要弄混了。当我们配置自己的服务器通过 HTTPS 进行通行的时候,需要在对应的端口上配置证书,否则客户端将无法通过 HTTPS 协议连接此端口。
服务端需要向客户端发送证书而客户端不需要向服务端发送证书
服务端证书的主要目的是为了:
- 证明服务端的身份:服务端通过证书向客户端证明自己是合法可信的服务器,防止客户端连接到恶意伪装的服务器。
- 建立加密通道:证书包含公钥,客户端会使用这个公钥加密协商密钥的数据,从而确保通信的保密性。
再复习一遍 TSL 握手的具体流程:
- 服务端发送证书:服务端向客户端发送自己的数字证书(包含公钥和其他信息)。
- 客户端验证证书:客户端检查证书的有效性(比如是否被可信的证书颁发机构签署、是否过期等)。
- 密钥协商:客户端使用服务端的公钥加密密钥协商信息,并发送给服务端。服务端使用私钥解密,双方生成共享密钥。
客户端通常不需要向服务端发送证书,因为:
- 服务端不需要验证客户端的身份(通常情况下):大部分 HTTPS 通信是为了保证用户隐私和数据加密,比如访问网页。此时,服务端只需确保向正确的客户端返回数据,不需要验证其身份。
- 对称加密通信已足够:通过服务端的公钥协商出的共享密钥用于对称加密,双方通信安全性已得到保障,服务端不需要额外的客户端身份验证。
虽然通常情况下客户端无需发送证书,但在一些特定场景中(如银行、企业内部系统),需要双向认证: - 客户端也会持有证书,用于证明自己的身份。
- 客户端向服务端发送自己的证书,服务端验证后才能继续通信。
双向认证的应用场景: - 高安全需求:比如在线银行、VPN 连接、企业级服务等。
- 具体流程:在双向认证中,除了服务端发证书给客户端,客户端也需要将自己的证书发送给服务端,双方互相验证对方身份。
总结 - 服务端发证书给客户端是为了证明身份和提供公钥。
- 客户端无需发证书给服务端,因为大多数应用场景不需要验证客户端的身份。
- 如果需要双向认证,客户端也可以发证书给服务端,但这是特殊场景的需求。
如何启用 HTTPS
首先,我们需要获取 TSL 证书,关于如何获取证书,请参考《如何获取 SSL/TSL 证书并自动续期》。
在 Nginx 中配置 HTTPS 的方法很简单,效果非常好,直接转发即可,可见转发给 HTTP 的请求,是解密过后了的,而不是未解密的。而且代理也是双向的,既代理发送到上游的流量,也代理从上游发出的流量。
http {
......
server {
# 对外以 9090 提供 HTTPS 服务
listen 9090 ssl ;
listen [::]:9090 ssl ;
server_name _;
# 证书地址
ssl_certificate "/etc/host_ssl/xiashuo.xyz.pem";
ssl_certificate_key "/etc/host_ssl/xiashuo.xyz.key";
# SSL 配置
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
# 被代理的,原本的 HTTP 服务
proxy_pass http://localhost:90;
}
}
}
其中,ssl_certificate
和 ssl_certificate_key
配置的是就是证书
在集群系统中,一般我们都会通过 Nginx 对外统一提供服务,在集群内部服务与服务之间,都是通过 HTTP 相互提供服务,而当这些服务要通过 Nginx 对外提供服务的时候,会通过另一个带 TSL 证书的接口代理处理出去,以提供 HTTPS 服务,在集群内部通过 HTTP 相互通信的主要原因是 TSL 握手是很耗时的,而且加密解密也影响效率,而且集群内部都是相互信任的,没有必要加密。
如何在抓包之后解密 HTTPS
当我们在 Chrome 浏览器中以 HTTPS 访问了一个网页,打开开发者工具,在 Network
中,点击这个 HTTPS 协议的请求,查看 Headers
和 Response
,我们可以直接看到明文信息,不是说 HTTPS 协议会进行加密吗?为什么我们可以看到明文呢?这是因为 Chrome 浏览器会保存建立 TSL 握手过程中的密钥(关于如何 TSL 握手,请看 HTTPS 的通信过程
小节),然后自动为你解密。
但是如果我们在别的 Chrome 以外的抓包工具中捕获到 HTTPS 网络包了,就没人为我们自动解密了,我们需要手动配置解密,
首先,我们需要配置一个环境变量,让 Chrome 将预主密钥(Pre-Master Secret)输出到一个日志文件中。然后,其他的工具,比如抓包工具 wireshark,可以通过这个日志文件里的秘钥再结合自己从网络包获取的其他值,来解密网络包,实际上 Wireshark 抓取 HTTPS 协议的包的时候就是通过这种方式解密的。
关于 Wireshark 如何解密 HTTPS 协议的包,请看《抓包工具》的
常见抓包场景