此前一篇文章用 wireshark 这个抓包工具调试了一下 HTTP 请求和响应。详细阐述了 TCP 连接和断开的整个过程。这篇文章尝试使用 wireshark 来抓取 TLS 封包,了解一下 HTTPS 请求和响应的整个过程。 ?
懒得看全文的直接拉到最下看 TLS 流程的图片解释
首先准备好 curl 和 wireshark,这些谷歌一下怎么安装。 ?
HTTPS 是基于 TLS 之上的,如果没有目标的私钥是没办法解密的,如果直接使用 wireshark 是看不到 TLS 层加密的信息的。
打开 wireshark 并开启抓包,在 curl 中发送一个请求:
再 wireshark 输入 tls 过滤请求,疑似 ip 地址为目标网站
输入该 ip 地址,确认是目标网站 httpbin,然后尝试查看返回的数据信息,因为 TLS 加密是看不到返回的 JSON 数据的
因 TLS 使用的是迪菲 - 赫尔曼密钥交换生成对称密钥的加密算法,因此需要获取到一系列生成密钥的必要信息后才可生成密钥解密数据。
先不着急怎么解决这个问题,首先回顾一下几个知识点,大概了解一下加密算法和 CA 数字证书和 TLS 加密流程:
远古以前用的是对称加密,这种加密和解密的密钥是同一个,因此极为不安全,一旦其中一个密钥泄露,那么就会导致加密文件被破解
后来发明了非对称加密,这种加密方式的逻辑就是公钥用来加密,私钥用来解密,一方使用另一方的公钥进行加密,传输密文给另一方,另一方再用私钥进行解密,这样没有拿到私钥就无法解密密文。但这种加密解密效率较低,后来就衍生出了混合加密,这种加密方式综合了非对称加密和对称加密。
混合加密首先使用非对称加密生成对称密钥,然后再使用对称密钥进行数据安全传输,这样加密解密的效率要高得多了。TLS 用到的迪菲 - 赫尔曼就是其中的一种
关于迪菲 - 赫尔曼密钥交换算法,这里简单提一下,这种算法有几个特点:
这个算法的加密流程是这样的:
这样对称密钥 PSASB 和 PSBSA 就合成完毕了,双方就可以使用这个对称密钥对传输的数据进行加密 ?
⚠️ 问题是 A 将 P 发送给 B,B 如何确认 P 就是真的来自 A 的呢,而不是受到中间人攻击篡改了 P,这就需要使用 CA 认证了,只要有 CA 认证后的数字签名并且通过 CA 的公钥能够验证那么就可以确认 P 就是来自 A 的。
因此这里提一下 CA 证书也简单提一下原理:
一个网站 A 想要获取数字证书,那么要走如下流程:
这样 A 的公钥 PA 就可以被认为确实是来自 A 的,因为有 CA 签发的数字证书认证和背书。 ?
⚠️ 还有一个问题是 CA 的公钥谁来认证呢?要是 CA 的公钥也被恶意替换了怎么办?那么就需要 CA 的 CA 来认证了,那么 CA 的 CA 的公钥谁来认证?根据这个逻辑,最后有一个 root CA,这个 CA 用来做最后的权威鉴定。
最后来回顾一下 TLS 的加密流程
TLS 是建立在 TCP 基础上的,因此必定需要先三次 TCP 握手建立 TCP 连接,然后再是建立 TLS
以上,我们看到生成的两个随机数和 Pre-master key 一起计算生成 session key 就是通过上文中提到过的迪菲 - 赫尔曼密钥交换算法实现的。客户端收到 CA 数字证书获取到服务端公钥进行加密,也符合上文中提到的 CA 认证流程。服务端私钥解密客户端使用服务端公钥加密,在上文中的非对称密钥部分也进行了讲解。因此 TLS 是一个运用到多种认证、加密的安全传输技术。除此之外,上文中没有提到的使用 HASH 计算的目的则是为了防止数据遭到篡改,这跟我们大家在网上下载软件,计算 md5 校验是一个原理。 ⚠️ 如有不正确的地方,各位请在评论区指正谢谢
首先上文提到过 wireshark 直接抓取 TLS 的封包是没办法看到解密后的数据的,那么我们需要通过一些手段获取到解密后的数据
那么如何才能解密获取数据呢,这里有篇文章可以看看 https://jimshaver.net/2015/02/11/decrypting-tls-browser-traffic-with-wireshark-the-easy-way/
It turns out that Firefox and Chrome both support logging the symmetric session key used to encrypt TLS traffic to a file. You can then point Wireshark at said file and presto! decrypted TLS traffic.
原理是浏览器会在系统中存在名为 SSLKEYLOGFILE
的环境变量已经设置的情况下,将每个 HTTPS 连接产生的客户端或服务端的随机数、preMasterSecret、MasterSecret 全部获取到并保存在这个环境变量指定的文件中。
开始动手实操,这里用的是 windows 系统,我们配置环境变量:
配置完成,这样浏览器就会写入密钥信息到指定路径的文件中
至于 macOS/Linux 自己谷歌一下如何设置环境变量,很简单不再赘述
打开 wireshark,点击配置信息指定 TLS 的 Pre-master key 路径为环境变量指定的那个文件路径
这样配置就算完成了,我们尝试一下打开 chrome 浏览器访问一个 https 网址:
这里访问了百度的首页,可以看到 wireshark 展现的已经是解密后的数据了
然后打开终端使用 curl 发送一个 https 请求
还是以 httpbin 为例,过滤 http 查看 wireshark 的结果:
右键 follow 一下
这就是整个 TCP 建立到 TLS 握手再到 HTTP 请求响应以及 TCP 断开的整个过程,我们逐一分析一下:
TCP 的此前文章已经说过了,这里也不再提了,直接看 TLS 部分:
Client Hello
Client Hello 阶段,客户端给服务端发送一个随机数,以及 Cipher Suites 客户端支持的所有加密套件
Server Hello
Server Hello 阶段,服务端给客户端发送一个随机数,以及选中的 Cipher Suite 加密套件
然后服务端继续发送给客户端 CA 数字证书以及 Server Key Exchange 和 Hello done 信息完成第一阶段的握手:
这个是证书:
这个是 Server Key Exchange,可以看到协商了一种加密算法:
这个是 Server Hello Done:
Client Finish
客户端发送一个 Client Key Exchange,Change Cipher Spec 和 Finished 报文
Finished Verify Data 包括至此连接的所有报文的校验信息,用服务端提供的公钥加密
客户端准备好切换为对称密钥加密
Server Finish
最后服务端返回一个 Change Cipher Spec 和 Server Finish
服务端准备好切换为对称密钥加密
TLS 握手成功
至此,TLS 握手成功,在 wireshark 中就可以看到接下来就是 HTTP 的请求响应封包了:
最后画了个简化版的脑图方便理解:
⚠️ 如有不正确的地方,各位请在评论区指正谢谢