我们知道,HTTP/2 引入了二进制分帧层(Binary Framing),将每个请求和响应分割成为更小的帧,并对它们进行了二进制编码。与此同时,HTTP/2 沿用了之前 HTTP 版本中的绝大部分语义,上层应用基本上感知不到 HTTP/2 的存在,这一点可以通过浏览器的网络调试工具得到验证。以下是使用 Chrome 访问 HTTP/2 网站的截图,网络面板中显示的内容与 HTTP/1 网站相比,只有一些细微的区别(头部字段都是小写,多了一些冒号开头的头部等)。
那么究竟要如何调试 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 的支持,首先请从下面这个地址获取最新的安装包:
根据自己系统选择合适的安装包后,全新或覆盖安装都可以。我在写本文时用的是「Wireshark 2.1.0-229-g3385c29 Intel 64.dmg」这个安装包。
由于主流浏览器都只支持 HTTP/2 Over TLS,也就是说当前 HTTP/2 网站都使用了 HTTPS,数据传输都经过了 SSL 加密。所以默认情况下,Wireshark 抓到的包是这样的,SSL 层之上的协议细节完全看不到:
另外一个著名的 HTTP 抓包工具 Fiddler 是通过开启本地代理进行抓包的,它能够解密 HTTPS 流量的原理很简单:首先 Fiddler 作为客户端跟服务端建立 TLS 连接,使用服务端的证书,处理请求和响应;然后 Fiddler 又作为服务端跟浏览器建立 TLS 连接,使用 Fiddler 的证书,处理请求和响应。所以 Fiddler 要解密 HTTPS 流量,需要先把它生成的根证书添加到系统受信任的根证书列表之中。
Wireshark 的抓包原理是直接读取并分析网卡数据,要想让它解密 HTTPS 流量,有两个办法:1)如果你拥有 HTTPS 网站的加密私钥,可以用来解密这个网站的加密流量;2)某些浏览器支持将 TLS 会话中使用的对称密钥保存在外部文件中,可供 Wireshark 加密使用。本文重点介绍第二种方法。
Firefox 支持生成上述第二种方式的文件,具体格式见这里:NSS Key Log Format。但 Firefox 只会在系统环境变量中存在 SSLKEYLOGFILE
路径时才会生成它,先来加上这个环境变量(以 OSX 为例):
接着,在 Wireshark 的 SSL 配置项里将这个文件选上。如下图:
通过终端启动 Firefox(确保能读取到环境变量):
这时候,再访问 HTTPS 网站,Firefox 应该会往 sslkeylog.log
文件中写入一些数据。检查无误后,就可以开启 Wireshark,选择合适的网卡开始抓包了(本文目的是抓取 HTTP/2 数据包,可以将 TCP 端口限定在 443,让抓到的数据少一些):
新版 Wireshark 在配置了 TLS 加密后,会自动识别并解析 HTTP/2 流量。通过 Firefox 访问想要抓包的 HTTP/2 网站,根据 IP 和协议过滤一下,就可以轻松看到想要的 HTTP/2 数据包了。如下图:
这种方法也可以用在解密使用 HTTP/1 的 HTTPS 网站上,大家可以自己动手试一试。