Wireshark 查看本地浏览器的 HTTPS 加密通信

继续 TLS(或 SSL, HTTPS) 的话题。在我们诊断 HTTP 请求时,为了验证代码中发送了什么样的请求,会用 curl 或 Postman 的辅助,但它们都可能会带上额外的请求头等信息,最为可靠的办法是用网络抓包工具如 Wireshark, 从中看到的 HTTP 文本协议内容才是真正往外发送的内容。可是对于 HTTPS 的协议数据用 Wireshark 抓取到了也没用,因为它是加密了的,作为 TLS 的 Payload, 如果不知道加密算法或密钥是解不开来的。客户端与服务端的密钥交换是采用非对称方式加密的,只通过抓网络包是不可能知道最终确定的密钥是什么,除非像 Zscaler 那样堂而皇之地作为中间人攻击(man in the middle attack)。

但既然是本地浏览器能理解的网页内容,只要浏览器留了口子的话,也是有办法在 WireShark  中显示出抓取到的 HTTPS 的内容,那就是设置环境变量 SSLKEYLOGFILE, 然后启动浏览器(FireFox 或 Chrome), 就会把通信过程中的密钥记录到文件中,WireShark  中引用该 SSLKEY  文件就能显示出确切的 HTTP 请求的内容。

为了加强理解 TLS 与 HTTP 的关系,我们回顾一下网络的协议层,通常我们会采用两种分层模型:OSI(Open System Interconnect: 开放系统互联) 七层模型 与 DoD(Department of Defense: 美国国防部) 四层模型。从下图我们将看到 TLS 和 HTTP 分属哪一层

从上图中看到 TLS 在七层模型中是处于表示层,HTTP 处理它的上层应用层,而在四层模型中传输控制层之上的都是应用层,所以 TLS 是处于应用层,而 HTTP 只是作为它的 Payload 而存在。从而确切的讲并不存 HTTPS 这样一种协议,而是 TLS 之上的 HTTP(HTTP over TLS)。也就为什么正常情况下抓取到的网络包只看到 TLS 层,而其中的整个 HTTP 协议数据都是加密的,包括 URL, 请求头与请求求体。

仍以上一篇 自签发证书配置 HTTPS 单向双向验证 中配置的 Nginx 为例,如果正常在浏览器中访问 https://server.local, 则在 Wireshark 中看到的内容是

看不到 HTTP 的请求内容,它是加密了的,作为 TLS 协议的 Encrypted Application Data。

这里也可以解除某些人对 HTTPS 的安全担忧,只要启用了 HTTPS,整个 HTTP 协议数据都是加密的,不光对请求/响应体加密传输,对请求/响应用头,以及地址栏中看到的完整 URL(包括请求参数)都是加密传输的。此时真正要防患的是隔壁有没有一个老王(man in the middle), 所以又发展出更安全的 mTLS,可是又不能让所有网站给所有客户分配一个客户端证书。

下面的操作就是要让在本地浏览时,Wireshark 的 Application Data 展示为解密后的 HTTP 协议内容,步骤如下

设置环境变量 SSLKEYLOGFILE

依据不同的操作系统来配置该环境变量,如在 macOS 或 Linux 下的终端中

export SSLKEYLOGFILE=/tmp/sslkeys.log

应用环境变量 SSLKEYLOGFILE 启动浏览器

mac OS 或 Linux 下在同一个终端中,FireFox 和 Chrome 支持环境变量 SSLKEYLOGFILE。比如要启动 FireFox 浏览器,以 mac OS 为例

/Applications/Firefox.app/Contents/MacOS/firefox

之后在该浏览器中访问 HTTPS 网站时就会把通信时用的密钥记录在所指定的文件中,Wireshark 抓取了 TLS 后,知道加密算法与相应的密钥就能解密出其中的 HTTP 协议内容。

用 Wireshark 捕获包并指定 sslkey 文件

在 Firefox 中访问 https://server.local, 我们在 Wireshark 中抓取包了相应的 TLS 包,并且注意到在 /tmp 目录下生成了 sslkeys.log 文件。

接下来要做的就是让抓取的包与 /tmp/sslkeys.log 进行关联。打开 Wireshark 的 Preferences/Protocols,找到 TLS,然后在 (Pre)-Master-Secret log filename 中指定 sslkey.log 文件

"OK" 后再回到 Wireshark 的主界面,原来的 Application Data 就变绿了(GET / HTTP/1.1 行由于选中了,背景才不是绿色),其中的 HTTP 内容也被解密了

有了这种办法,对于本地调试 HTTPS 也容易了许多。

我们来看下生成的 sslkeys.log 的大致内容

包括 TLS 的握手过程交换的密钥,随机码以及最后通信用的密钥。

附抓取的包 https_dump.pcap 和相应的 sslkeys.log 文件,有兴趣的话可以用 Wireshark 打开 https_dump.pcap 加上 filter: tcp.port=443 就能显示上面的第一张 Wireshark 图片的内容,如果在 TLS 关联上 sslkeys.log 文件就会显示第二张 Wireshark 图片的内容。

另外:在我们在 Wireshark 关联 sslkeys.log 文件时注意到 Wireshark 还能指定 RSA keys list, 必要时可研究一下它的用法。

链接:

  1. 一文读懂OSI七层模型与TCP/IP四层的区别/联系
  2. How to Decrypt SSL using Chrome or Firefox and Wireshark in Linux
  3. Wireshark Tutorial: Decrypting HTTPS Traffic
  4. everything curl / SSLKEYLOGFILE

本文链接 https://yanbin.blog/wireshark-inspect-tls-encrypted-packets/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments