HTTP/2 流量调试
當(dāng)前主要可以通過(guò)瀏覽器和Wireshark等工具調(diào)試HTTP/2流量。
使用瀏覽器調(diào)試HTTP/2流量
HTTP/2 引入二進(jìn)制分幀層(Binary Framing),將每個(gè)請(qǐng)求和響應(yīng)分割為更小的幀,并對(duì)它們進(jìn)行二進(jìn)制編碼。與此同時(shí),HTTP/2 沿用之前 HTTP/1.1中的絕大部分語(yǔ)義,上層應(yīng)用基本上感知不到 HTTP/2 的存在。通過(guò)瀏覽器提供的網(wǎng)絡(luò)調(diào)試工具我們可以清晰地看到請(qǐng)求和響應(yīng)的詳細(xì)信息。
對(duì)于Chromium瀏覽器,打開(kāi)"更多工具(L) -> 開(kāi)發(fā)者工具(D)",然后選中"Network",并選中要查看的文件,就可以清晰地看到HTTP/2請(qǐng)求及響應(yīng)的信息了。如:
從上圖可以看到,HTTP/2資源的內(nèi)容,與HTTP/1.1資源的內(nèi)容相比,只有一些細(xì)微的變化,如所有的頭部字段名都是小寫(xiě)的,引入了以":"開(kāi)頭的偽首部字段等。
然而,瀏覽器的調(diào)試工具只能看到請(qǐng)求和響應(yīng)的信息。對(duì)于連接建立、數(shù)據(jù)傳輸,及流控這樣的過(guò)程信息,瀏覽器的調(diào)試工具就顯得無(wú)能為力了。這些更細(xì)節(jié)的信息可以通過(guò)Wireshark來(lái)看。
使用 Wireshark 調(diào)試 HTTP/2 流量
盡管HTTP/2規(guī)范并沒(méi)有嚴(yán)格要求只能基于TLS傳輸HTTP/2流量,然而目前基于TLS傳輸HTTP/2已然成為事實(shí)的標(biāo)準(zhǔn)了。絕大部分提供HTTP/2服務(wù)器的網(wǎng)站都基于TLS來(lái)提供,常見(jiàn)的客戶端瀏覽器,如Chrome,Firefox更是完全不提供對(duì)明文傳輸?shù)腍TTP/2的支持。因而通過(guò)Wireshark調(diào)試HTTP/2流量最主要的即是解密HTTPS流量,進(jìn)而借助Wireshark對(duì)HTTP/2數(shù)據(jù)的解析,看到客戶端與服務(wù)器之間詳細(xì)的幀交互過(guò)程。
Wireshark 的抓包原理是直接讀取并分析網(wǎng)卡數(shù)據(jù),要想讓它解密 HTTPS 流量,有兩個(gè)辦法:1)如果擁有 HTTPS 網(wǎng)站的加密私鑰,可以用來(lái)解密這個(gè)網(wǎng)站的加密流量;2)某些瀏覽器支持將 TLS 會(huì)話中使用的對(duì)稱(chēng)加密密鑰保存在外部文件中,可供 Wireshark 解密之用。
設(shè)置SSLKEYLOGFILE環(huán)境變量解密HTTPS流量
Firefox 和 Chrome 都支持生成上述第二種解密方式所需的文件,具體格式見(jiàn) NSS Key Log Format。但只有設(shè)置了系統(tǒng)環(huán)境變量SSLKEYLOGFILE,Firefox 和 Chrome 才會(huì)生成該文件,它們將這個(gè)系統(tǒng)變量的值作為文件保存的路徑。先來(lái)加上這個(gè)環(huán)境變量(Ubuntu):
$ mkdir ~/sslkeylogfile && touch ~/sslkeylogfile/keylogfile.log$ echo -e '\nexport SSLKEYLOGFILE=~/sslkeylogfile/keylogfile.log' >> ~/.bash_profile && . ~/.bash_profile接著,通過(guò)選擇Edit -> Preferences... -> Protocols -> SSL打開(kāi)Wireshark 的 SSL 配置面板(Ubunut版,Mac版通過(guò)Wireshark -> Preferences...打開(kāi)首選項(xiàng)),在「(Pre)-Master-Secret log filename」選項(xiàng)中選擇SSLKEYLOGFILE文件,或輸入該文件的路徑。如下圖:
ssl_config.png
最好將「SSL debug file」也配上,這樣解密過(guò)程中的日志都會(huì)記錄下來(lái),便于調(diào)試分析。
通過(guò) 終端 啟動(dòng) Firefox 或 Chrome(確保這些瀏覽器能讀取到環(huán)境變量):
$ chromium-browser這時(shí)再訪問(wèn) HTTPS 網(wǎng)站,sslkeylog.log文件中應(yīng)該包含瀏覽器寫(xiě)入的數(shù)據(jù)。如下面這樣:
$ cat ~/sslkeylogfile/keylogfile.logCLIENT_RANDOM 24103980248f266808400da7e48058f6c779b4b98fe8cae45981bafe7502b8ff 5e7e3a526fbf8c5a3567758f6aa412ea6c36c52d98e9a3dfde1d16f09714551bc64f62ca3cd9df2448b12dbf995d0b14 CLIENT_RANDOM 31c9cac267465543d6ea1ea358dd41fc9ed02aa8af45b0238b82e50915bc3360 dadf649c846b125dad5b1215e9d45ee34ba5241ecbc4856820ea7843177dc424a575fd788f007241c0252c718426dd92 CLIENT_RANDOM 36b8759c3bbb3df2645382240384675f1615f4a432ca7c58bf142776f752ee05 365c321e8d91834da7e8d44cbb963b2bc1b90f100a50fb7831bd5b9b7ec62d94c9a6de99da78c3c6aac93568cc675113 CLIENT_RANDOM 24a461fc4ae2295b81dc4eab6aff2e520e0fc2623091b249f59bfb46b1c3567d e2c8b46febbb61f0fa3e6a6857cd27fe95aa1a7616a522115488f35f30c3092d05b295cba99429d7c16d857cfb87953e CLIENT_RANDOM dcc1b0688d4dd99b3b5a4cacccfb9fa5d4861c439385abfb37cd4f98ed212091 3c6bb8767ddb4e6797880aadf5f59f39edaf15bc17c7a3632603803bffec45239261b9ae87d42495952c86c65158dbb4 CLIENT_RANDOM c96b42c46769d87fc06884da879a2f274047356ee3516f944aa0f37f72bbed0e 758e59ee207ff1667ee6643eb31d62aacb4a3fde3e39ab0654a003b0b015acd7e53de41ea754255e4bade1f25897643a CLIENT_RANDOM 766c0a2f84030be01513ffff1c36bff61872f0a8e039a40694eeee5b3a65c4ca efbdbc6cafdd32891df40daaa8d2c4778db889512c4e6ccd8a15a7f1e34ab55d7a657021eb9954883dc320cc632e8755 CLIENT_RANDOM b91cbe5fb40149006dbf95a74f1a8f9f0999a78c27dae42d169ca50521477c2c b3e9963f25598e9841ae58857ce13a891c22275f7f2d5c260446cba7355ccdcf41eeabe8f050350078ffe7a16a7c5219 CLIENT_RANDOM de8e0dbdc518459724cf5ed3cc09802c96fa558abe7c95ec4f0748700bc3e229 0cda6e9665758c54819cc00a09eb5f4249eb33519a16ae62911ffff090539aebd3138ebb4ee0ba7cab6630b3e255fffc CLIENT_RANDOM 6798fa4e2396f700f6309d55721badf73081ed2a8066db2f7bf652245c61076c 025a4679f2d399433a7dc9604f1b1a970dcc54b6da5166a188b061ece87cac1919e7b56be8455cf24ddffe1083694bb1 CLIENT_RANDOM d89d9e38c21af551d816f451ac3b25d29899f5623fa375f7c55897c06310e784 e9d56f1b084327850c96e30fa87488e7d83fcca7e5cd2200876aa8354d841d5432f339db04041fda5f79202c528e5399 CLIENT_RANDOM 5db78a4b93747b795867ed5800ed2f0c763d74f40fd9859e358689efcc3082c3 3e8edf030deae2d2ff78858b96d7525527e4bbdffe4caf62014a1977f008a7a9a6e96f08e07624a48ad45d45a3ef13c5 CLIENT_RANDOM 2902990ba00c5ad72fddf9a82fd78bdc40e347d423f5aaff71956780683b4df7 f51e107ad5db85ff16da162abb050482b196ffa0f99c2c1e834b73dd46454d322b53a85c14e5a266e05be20d19b1fd2a ......檢查無(wú)誤后,就可以開(kāi)啟 Wireshark,選擇合適的網(wǎng)卡開(kāi)始抓包。為了減少不必要的數(shù)據(jù)包對(duì)我們分析的干擾,我們可以只針對(duì)某個(gè)域名的TCP 443端口來(lái)抓包,以減少抓取的數(shù)據(jù)包的數(shù)量,如:
Capture Filter
新版 Wireshark (如我目前在用的Version 2.0.2) 在配置了 TLS 解密后,會(huì)自動(dòng)識(shí)別并解析 HTTP/2 流量。訪問(wèn)想要抓包的 HTTP/2 網(wǎng)站,就可以輕松看到想要的 HTTP/2 數(shù)據(jù)包了。如下圖:
wireshark_http2.png
這種方法也可以用在解密使用 HTTP/1 的 HTTPS 網(wǎng)站上。
每次都要從終端啟動(dòng)瀏覽器還是挺麻煩的,我們也可以為GUI設(shè)置環(huán)境變量,以便于我們不在命令行終端啟動(dòng)瀏覽器也可以解密HTTPS流量。方法是:
$ sudo echo -e '\nexport SSLKEYLOGFILE=~/sslkeylogfile/keylogfile.log' >> /etc/profile也可以通過(guò)其它任何個(gè)人偏好的編輯器為/etc/profile添加export那一行。更新了/etc/profile之后,注銷(xiāo)當(dāng)前登錄并重新登錄。在GUI中啟動(dòng)chromium瀏覽器,也可以通過(guò)Wireshark解密HTTPS流量了。不過(guò)要注意,這個(gè)設(shè)置對(duì)所有用戶均全局生效。為了系統(tǒng)安全最好在利用Wireshark調(diào)試HTTPS流量之后移除這一設(shè)置。
Wireshark就像一副眼鏡一樣,戴上它之后,可以讓我們對(duì)網(wǎng)絡(luò)世界發(fā)生的一切看得更加清楚,然而即使有了這樣強(qiáng)大好用的工具,要想對(duì)協(xié)議有真正的理解,仔細(xì)地閱讀協(xié)議規(guī)范文件也是必不可少的,關(guān)于HTTP/2協(xié)議的細(xì)節(jié),可以參考HTTP2規(guī)范(RFC7540)、HPACK:HTTP/2的首部壓縮 (RFC7541)和應(yīng)用層協(xié)議協(xié)商(ALPN)規(guī)范(RFC7301)。
導(dǎo)入服務(wù)器私鑰解密HTTPS流量
還可以通過(guò)為Wireshark導(dǎo)入服務(wù)器RSA私鑰來(lái)解密HTTPS流量。方法是選擇Edit -> Preferences... -> Protocols -> SSL打開(kāi)Wireshark 的 SSL 配置面板,點(diǎn)擊"RSA keys list"后的"Edit..."按鈕:
rsa_key_record.png
添加一個(gè)RSA私鑰項(xiàng),輸入適當(dāng)?shù)腎P地址,端口,解密后的協(xié)議,及私鑰文件的路徑,其中私鑰必須存為 PEM 格式,這種格式的私鑰文件類(lèi)似于下面這樣:
-----BEGIN RSA PRIVATE KEY----- MIIJKQIBAAKCAgEAw5JweP8ACiLHFAs9syY0yzdjJh3WQntcq1HM9xJXJrHRT1+n Als88+bh7HxmYbrYXtZhYEjW00wjmlB1Sy0biX17VS8SY7Ssx7XRRJXtovSd7nc8 KwZI2Rgh0e7PXCatwhEonCdlEZTEHQ9eTE8Acc9dH0BLml47sEJFxWgBYinCkrWt jRMR234CZRRqXUtmFgjUq5DcBignzYTAtzAi/1RxwjuNfYtSw6jx7mNCKt1Np3Bm ....... some 20-100 lines of base64 encoded data ............... +TtJwCHfBRGIyI3hGA1eBa8Lc3nhXPjUwtp7q+2gwpsq/25gt2tiUfSak7frhFal 9gP00/d9nJXwh2UR3G/oEsXWORfRUVAgjyzhXrrJ+uQJBgUVEZ1D0lI6qfdc -----END RSA PRIVATE KEY-----對(duì)于nginx服務(wù)器來(lái)說(shuō),通常通過(guò)ssl_certificate_key項(xiàng)配置的是站點(diǎn)私鑰,這個(gè)私鑰通常是在申請(qǐng)證書(shū)時(shí),通過(guò)類(lèi)似于如下這樣的方式產(chǎn)生:
$ openssl genrsa 4096 > domain.key關(guān)于私鑰格式的更多信息,可以參考Wireshark的SSL Wiki。
但這種方法對(duì)客戶端與服務(wù)器協(xié)商的加密套件有要求。如果加密套件的密鑰交換算法是ECDHE,也就是當(dāng)前大多數(shù)HTTPS流量所選擇的算法,則解密HTTPS流量將失敗??梢酝ㄟ^(guò)Wireshark抓取的TLS握手的Server Hello消息來(lái)查看客戶端與服務(wù)器協(xié)商的加密套件:
Server Hello.png
客戶端與服務(wù)器協(xié)商加密套件的過(guò)程大體為,客戶端在其TLS握手的Client Hello消息的Cipher Suites字段中發(fā)送自己支持的加密套件。如通過(guò)curl訪問(wèn)http2資源:
$ curl --http2 -v https://www.wolfcstech.com/可以看到curl支持的加密套件集:
client_cipher_suites.png
對(duì)于nginx,我們通過(guò)ssl_ciphers選項(xiàng)為其配置加密套件,如:
# https://github.com/cloudflare/sslconfig/blob/master/confssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;ssl_prefer_server_ciphers on;加密套件以":"分隔。服務(wù)器從為其配置的加密套件集中選擇排序最靠前的客戶端支持的加密套件。對(duì)于上面的服務(wù)器加密套件集配置,用curl訪問(wèn)服務(wù)器,協(xié)商出來(lái)的加密套件為T(mén)LS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f),這種加密套件的密鑰交換算法正是ECDHE,也即不支持Wireshark加密的算法。
我們可以通過(guò)修改服務(wù)器的配置,以便Wireshark可以解密HTTPS流量。修改之后nginx服務(wù)器的加密套件配置為:
# https://github.com/cloudflare/sslconfig/blob/master/confssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:RSA+AES128:EECDH+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;ssl_prefer_server_ciphers on;與前面那個(gè)配置相比,僅有的改動(dòng)是對(duì)調(diào)了RSA+AES128和EECDH+AES128兩個(gè)加密套件的位置。再次通過(guò)curl訪問(wèn)服務(wù)器,可以看到HTTP2流量被解密了:
curl_http2.png
這次協(xié)商的加密套件為T(mén)LS_RSA_WITH_AES_128_GCM_SHA256 (0x009c),其密鑰加密算法為RSA。
不過(guò)此時(shí)通過(guò)chrome瀏覽器訪問(wèn)網(wǎng)站,就會(huì)發(fā)現(xiàn)頁(yè)面已經(jīng)打不開(kāi)了,如下圖所示:
cipher_suite_config_error_for_http2.png
仔細(xì)看的話,可以看到ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY。這是由于為了安全性考慮,HTTP/2規(guī)范建立了加密套件黑名單,并強(qiáng)制要求HTTP/2服務(wù)不得配置這樣的加密套件。Chromium瀏覽器嚴(yán)格遵守HTTP/2規(guī)范,且在TLS協(xié)商階段,服務(wù)器選擇了加密套件黑名單中的TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c),因而連接直接被斷開(kāi)了。通過(guò)Wireshark抓包來(lái)看:
http2_goaway.png
可見(jiàn)是HTTP2層,在與服務(wù)器建立連接之后,瀏覽器就立即發(fā)送GOAWAY幀斷開(kāi)了連接。
然而curl似乎并沒(méi)有嚴(yán)格遵守HTTP/2規(guī)范。
是否可以通過(guò)為Wireshark添加RSA私鑰解密HTTPS流量的決定性因素,在于客戶端與服務(wù)器協(xié)商的加密套件,而不在于通過(guò)HTTPS傳輸?shù)牧髁渴荋TTP/1.1的還是HTTP/2的。不過(guò)可以通過(guò)這種方法讓W(xué)ireshark解密的所有加密套件都已經(jīng)進(jìn)了HTTP/2規(guī)范的加密套件黑名單,因而對(duì)于符合規(guī)范的HTTP/2流量傳輸,都是無(wú)法通過(guò)這種方法來(lái)解密流量的。
判斷HTTP2是否啟用
如前面所述,在某些情況下,直接解密HTTP/2流量確實(shí)是難以實(shí)現(xiàn)的。而如果我們的需求僅僅是判斷HTTP/2是否啟用的話,則還是可以通過(guò)Wireshark實(shí)現(xiàn)的。
HTTP/2在TCP連接建立完成之后,TLS握手的過(guò)程中,會(huì)進(jìn)行協(xié)議協(xié)商,以確定客戶端和服務(wù)器之間通信最終所用的應(yīng)用層協(xié)議。這個(gè)協(xié)議協(xié)商協(xié)議成為ALPN。ALPN是TLS的特性,客戶端的SSL/TLS庫(kù)及使用SSL/TLS庫(kù)的模塊,如HTTP棧,只要支持這一擴(kuò)展,在發(fā)送Client Hello消息時(shí),就會(huì)帶上相關(guān)消息,如:
ALPN Extension
服務(wù)器的SSL/TLS庫(kù)及Web服務(wù)器如果能識(shí)別這一擴(kuò)展,會(huì)在Server Hello消息中的相同擴(kuò)展處放上服務(wù)器所選擇的用戶雙方通信的協(xié)議標(biāo)識(shí)。如果為服務(wù)器配置了支持HTTP/2時(shí),Server Hello消息的ALPN擴(kuò)展值將為h2,否則將是http/1.1,如:
ALPS_01.png
因而盡管對(duì)于無(wú)法解密TLS流的HTTP/2流,在Wireshark中無(wú)法查看傳輸更多的細(xì)節(jié)過(guò)程,但還是可以通過(guò)Wireshark抓取到的Server Hello消息的ALPN擴(kuò)展值判斷協(xié)議協(xié)商的結(jié)果。
參考文檔:
SSL - The Wireshark Wiki
Ubuntu系統(tǒng)環(huán)境變量詳解
使用 Wireshark 調(diào)試 HTTP/2 流量
三種解密 HTTPS 流量的方法介紹
為curl命令啟用HTTP2支持
總結(jié)
以上是生活随笔為你收集整理的HTTP/2 流量调试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 非对称加密与证书
- 下一篇: Caddy Web服务器QUIC部署