我們知道,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」這個安裝包。
Update @ 11.8,我今天試了一下官網的「Wireshark 2.0.0rc2 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 為例):
1 |
mkdir ~/tls |
接著,在 Wireshark 的 SSL 配置皮膚的 「(Pre)-Master-Secret log filename」選項中這個檔案選上。如下圖:
「SSL debug file」也建議配上,這樣解密過程中的日誌都會記錄下來,便於除錯。
通過終端啟動 Firefox(確保能讀取到環境變數):
1 |
open /Applications/Firefox.app |
這時候,再訪問 HTTPS 網站,Firefox 應該會往 sslkeylog.log
檔案中寫入一些資料。檢查無誤後,就可以開啟 Wireshark,選擇合適的網路卡開始抓包了(本文目的是抓取 HTTP/2 資料包,可以將 TCP 埠限定在 443,讓抓到的資料少一些):
新版 Wireshark 在配置了 TLS 加密後,會自動識別並解析 HTTP/2 流量。通過 Firefox 訪問想要抓包的 HTTP/2 網站,根據 IP 和協議過濾一下,就可以輕鬆看到想要的 HTTP/2 資料包了。如下圖:
這種方法也可以用在解密使用 HTTP/1 的 HTTPS 網站上,大家可以自己動手試一試。