使用 Wireshark 调试 HTTP/2 流量

我们知道,HTTP/2 引入了二进制分帧层(Binary Framing),将每个请求和响应分割成为更小的帧,并对它们进行了二进制编码。与此同时,HTTP/2 沿用了之前 HTTP 版本中的绝大部分语义,上层应用基本上感知不到 HTTP/2 的存在,这一点可以通过浏览器的网络调试工具得到验证。以下是使用 Chrome 访问 HTTP/2 网站的截图,网络面板中显示的内容与 HTTP/1 网站相比,只有一些细微的区别(头部字段都是小写,多了一些冒号开头的头部等)。

imququ-network

那么究竟要如何调试 HTTP/2 流量呢?HTTP/2 中的 Server Push、Prioritization 等功能,要如何才能看到并分析呢?Chrome 本身提供了一个非常不错的工具,在 Chrome 地址栏输入 chrome://net-internals/#http2 即可进入。这个工具会列出浏览器当前所有活跃的 HTTP/2 Session,点击具体的 Session ID,可以看到全部帧信息。

但 Chrome 的工具看到的信息毕竟经过了解析和筛选,不如原始信息全面,也没办法在其他浏览器例如 Firefox 中使用。本文介绍一个更为通用的 HTTP/2 调试工具:Wireshark。

Wireshark 是一个无比强大的网络封包分析工具,大家对它应该不陌生。新版 Wireshark 才增加了对 HTTP/2 的支持,首先请从下面这个地址获取最新的安装包:

https://www.wireshark.org/download/automated/

根据自己系统选择合适的安装包后,全新或覆盖安装都可以。我在写本文时用的是「Wireshark 2.1.0-229-g3385c29 Intel 64.dmg」这个安装包。

Update @ 11.8,我今天试了一下官网版本(下载地址)」,也没问题。

由于主流浏览器都只支持 HTTP/2 Over TLS,也就是说当前 HTTP/2 网站都使用了 HTTPS,数据传输都经过了 SSL 加密。所以默认情况下,Wireshark 抓到的包是这样的,SSL 层之上的协议细节完全看不到:

wireshark-ssl

另外一个著名的 HTTP 抓包工具 Fiddler 是通过开启本地代理进行抓包的,它能够解密 HTTPS 流量的原理很简单:首先 Fiddler 作为客户端跟服务端建立 TLS 连接,使用服务端的证书,处理请求和响应;然后 Fiddler 又作为服务端跟浏览器建立 TLS 连接,使用 Fiddler 的证书,处理请求和响应。所以 Fiddler 要解密 HTTPS 流量,需要先把它生成的根证书添加到系统受信任的根证书列表之中。

Wireshark 的抓包原理是直接读取并分析网卡数据,要想让它解密 HTTPS 流量,有两个办法:1)如果你拥有 HTTPS 网站的加密私钥,可以用来解密这个网站的加密流量;2)某些浏览器支持将 TLS 会话中使用的对称密钥保存在外部文件中,可供 Wireshark 加密使用。本文重点介绍第二种方法。

Firefox 和 Chrome 都支持生成上述第二种方式的文件,具体格式见这里:NSS Key Log Format。但 Firefox 和 Chrome 只会在系统环境变量中存在 SSLKEYLOGFILE 路径时才会生成它,先来加上这个环境变量(以 OSX 为例):

mkdir ~/tls && touch ~/tls/sslkeylog.log

#zsh
echo "\nexport SSLKEYLOGFILE=~/tls/sslkeylog.log" >> ~/.zshrc && source ~/.zshrc

#bash
echo "\nexport SSLKEYLOGFILE=~/tls/sslkeylog.log" >> ~/.bash_profile && . ~/.bash_profile

接着,在 Wireshark 的 SSL 配置面板的 「(Pre)-Master-Secret log filename」选项中这个文件选上。如下图:

wireshark-ssl-debug

「SSL debug file」也建议配上,这样解密过程中的日志都会记录下来,便于调试。

通过终端启动 Firefox 或 Chrome(确保能读取到环境变量):

open /Applications/Firefox.app
open /Applications/Google\ Chrome.app

这时再访问 HTTPS 网站,sslkeylog.log 文件中应该有浏览器写入的数据了。检查无误后,就可以开启 Wireshark,选择合适的网卡开始抓包(本文目的是抓取 HTTP/2 数据包,可以将 TCP 端口限定在 443,让抓到的数据少一些):

wireshark-capture

新版 Wireshark 在配置了 TLS 加密后,会自动识别并解析 HTTP/2 流量。访问想要抓包的 HTTP/2 网站,根据 IP 和协议过滤一下,就可以轻松看到想要的 HTTP/2 数据包了。如下图:

wireshark-http2

这种方法也可以用在解密使用 HTTP/1 的 HTTPS 网站上,大家可以自己动手试一试。

本文链接:参与评论 »

--EOF--

提醒:本文最后更新于 408 天前,文中所描述的信息可能已发生改变,请谨慎使用。

专题「HTTP/2 相关」的其他文章 »

Comments