WiresharkでHTTP/2をパケットキャプチャする

20190417追記
HTTP/3はこちら「WiresharkでのQUICの復号(decrypt) - ASnoKaze blog


20151030追記
TLSを利用するHTTP/2では、秘密鍵を設定しても通信を復号することは出来ません。
HTTP/2の鍵交換はPFSなので、下記も参考にして下さい

Wireshark で HTTP/2 over TLS の通信をダンプする方法」
https://gist.github.com/summerwind/a482dd1f8e9887d26199



この記事は HTTP2 Advent Calendar の 9 日目の投稿です。


初めましてゆきと申します。HTTP/2アドベントカレンダーにはガチ勢しかおらず戦々恐々としております。
アドベントカレンダーネタとしては、Push周りを書こうとしてたのですが先日Push周りの素晴らしい記事が投稿されてしまいましたので、書くことに非常に困ったのですがWiresharkについて書いていこうかと思います。すみません。
その話は又どこかで出来るかもしれません。楽しみにお待ち頂ければ幸いです。

Wireshark

有名なパケットキャプチャ・解析ツールとしてWiresharkは有名かと思います。僕も普段から使用し、不意のネットワークトラブルと格闘しています。
このWiresharkですが以前からHTTP/2に対応していますが、最新の開発版ではhttp/2 draft14に対応しています。

なぜWiresharkを使うのか

プロトコルを実装する際、すでにWiresharkが対応している場合、非常に有用です。


例えば、僕がアドベントカレンダーネタで未だに実装のないPHPでClient(糞コード:こちら)を書こうとした時など、やはり上手く行かないといった事が出てくるわけです、そういう時に



不具合が一瞬で特定できます

  • HEADERSフレームを送信する所まで処理が進んでいる
  • 送ったFlagsの値がどうもおかしい
  • 実際に該当するバイナリ部分の場所


また、統計情報もグラフで表示できますので通信量の比較なども可能です。
さらに凝った事をしたいという人もLuaでごにょごにょすることもできるので、最悪スクリプトを書くことで解決できます。

Wiresharkを使う上で...

HTTP/2として解釈されない場合がある


場合によっては、HTTP/2として解釈されない場合があるためDecode ASからこれらの通信がHTTP/2として解釈するように選択すればdecode結果が正しく表示されます

暗号化されて読めない

HTTP/2のブラウザ実装で暗号化のみ対応したものが殆どです。
当たり前ですが、暗号化は盗聴されないためのものであり、パケットキャプチャしただけでは復号出来ません。以前であれば自分のサーバの秘密鍵で復号出来ましたが、HTTP/2で指定されている暗号スイートはForward secrecyという特性を有しています。そのため秘密鍵を用いても複合できません。(これは、盗聴データを保存しておきマシンリソース・解読技術が向上した将来に秘密鍵を復元されても解読されないようにするためです)


そのため、平文で通信する必要があります。
もしくは、Forward secrecy特性のない暗号スイートを指定できるのであれば秘密鍵から復号することも可能です。
(Firefoxでは、about:configより「network.http.spdy.enforce-tls-profile」で設定可能です)

通信の途中からキャプチャしてもヘッダが表示されない

HTTP/2はHPACKというヘッダ圧縮の仕組みを使用しています。そのため、通信の途中からキャプチャしたとしても当たり前ですがヘッダを表示することは出来ません


アップグレードにも対応

HTTP/1.1から通信を開始するアップグレードについても対応しています


もちろんFilterも使えます

特定のフレームだけを表示することも出来ます。例えばstream_idが0のものだけ表示するのであれば



他にも以下のようなフィルターがあります

Filter 説明
http2.headers http.[フレーム名]で特定のフレーム
http2.header.name == :method 特定のHTTPヘッダを持つフレーム
http2.flags.end_stream == 1 ストリームの終端フレーム、他のflagsももちろん選択できます


もちろん、「ip.src == 127.0.0.1 && http2」のような絞り方や、有用か分かりませんが「http2.flags.padded == http2.flags.priority」といった絞り方も出来ます。

サーバがCUIなのだが

tcpdump 入れましょう。「tcpdump -i any -w out.pcap」で吐いたファイルをWiresharkに食べさせる事ができます。

終わりに

Wiresharkに慣れていると何かの時に便利だったりしますし、楽しいです。
是非これからもパケットをキャプチャしていきましょう。