Hatena::ブログ(Diary)

あすのかぜ Twitter

2014-12-08

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

Wireshark で HTTP/2 over TLS通信をダンプする方法

https://gist.github.com/summerwind/a482dd1f8e9887d26199


HTTP/2の鍵交換はPFSなので、上記も参考にして下さい(20151030追記)



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


初めましてゆきと申します。HTTP/2アドベントカレンダーにはガチ勢しかおらず戦々恐々としております。

アドベントカレンダーネタとしては、Push周りを書こうとしてたのですが先日Push周りの素晴らしい記事が投稿されてしまいましたので、書くことに非常に困ったのですがWiresharkについて書いていこうかと思います。すみません。

その話は又どこかで出来るかもしれません。楽しみにお待ち頂ければ幸いです。


Wireshark

有名なパケットキャプチャ・解析ツールとしてWiresharkは有名かと思います。僕も普段から使用し、不意のネットワークトラブルと格闘しています。

このWiresharkですが以前からHTTP/2に対応していますが、最新の開発版ではhttp/2 draft14に対応しています。


なぜWiresharkを使うのか

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


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


f:id:ASnoKaze:20141208224140p:image


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

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

また、統計情報もグラフで表示できますので通信量の比較なども可能です。

さらに凝った事をしたいという人もLuaでごにょごにょすることもできるので、最悪スクリプトを書くことで解決できます。


Wiresharkを使う上で...

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

f:id:ASnoKaze:20141208231243p:image

場合によっては、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というヘッダ圧縮の仕組みを使用しています。そのため、通信の途中からキャプチャしたとしても当たり前ですがヘッダを表示することは出来ません

f:id:ASnoKaze:20141208234107p:image



アップグレードにも対応

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

f:id:ASnoKaze:20141208233019p:image



もちろんFilterも使えます

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

f:id:ASnoKaze:20141208234849p:image



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

Filter説明
http2.headershttp.[フレーム名]で特定のフレーム
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に慣れていると何かの時に便利だったりしますし、楽しいです。

是非これからもパケットをキャプチャしていきましょう。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証