パケット監視ツールWiresharkについて


# 1. Wireshark

[Wireshark](https://www.wireshark.org/)はパケット単位でネットワークを監視できるオープンソースのツールである。Windows, Macにはインストーラがある。また、いくつかのLinux distributionはWiresharkのパッケージをサポートしているものの、古いバージョンしか入っていない可能性があるため、直接インストールすることが推奨されている（参考:[Wireshark公式ドキュメント](https://www.wireshark.org/docs/wsug_html_chunked/ChapterBuildInstall.html)）。未確認だが、[AskUbuntu](https://askubuntu.com/questions/700712/how-to-install-wireshark)よるとUbuntuでは以下のコマンドで起動できるらしい。
```bash
sudo add-apt-repository ppa:wireshark-dev/stable
sudo apt-get update
sudo apt-get install wireshark

#Run Wireshark
sudo wireshark 
```

実際のWiresharkの画面は以下の通り。


```plantuml
@startuml
<style>
root {
  Padding 0
  Margin 0
}
footer {
  FontColor black
  FontSize 22
}
</style>
footer 図1　Wiresharkの実際の使用画面
title <img:https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636063/8be6c4ac-a8a2-16e5-5055-f624cfc413d6.png>
@enduml
```

実際の通信は非常に多くのパケットのやり取りを様々なサーバと行っているが、上図の通り、IPアドレスを指定して検索できるため、通信先サーバを指定してパケット交換のトラッキングを行える。フィルタリング方法はIPアドレス以外にも、TCP通信に限定したり、パケットのInfoの内容の文字列検索等もできるため、簡単に目当てのサーバとの通信を見つけられる。

# 2. 背景: そもそもなぜWiresharkを使いたくなったか
研究として開発しているLoad Testing Toolが、1,000 requests/secを超えるようなスループットでリクエストをしようとしているときに、テスト開始から1~10秒の間、スタックしてしまって実際にリクエストが送れていないように見えていた。
そこで、以下のように、コードの中にカウンタを入れてモニタリングしたところ、HTTPコネクションを開始する箇所で詰まってしまっているように見えたため、実際にどのように通信が行われているかを分析することで問題の原因を特定できると考えた。

```Java:HTTPリクエスト送信メソッド
private void sendHTTPRequest(HttpURLConnection connection,
                             byte[] payloadBytes,
                             RequestExecutionMonitor requestExecutionMonitor) throws IOException {
        if(requestExecutionMonitor != null){
            requestExecutionMonitor.incrementAttemptCount();
        }
        connection.connect();
        if(requestExecutionMonitor != null){
            requestExecutionMonitor.incrementConnectionCount();
        }
        try (OutputStream os = connection.getOutputStream()) {
            os.write(payloadBytes);
            if (requestExecutionMonitor != null) {
                requestExecutionMonitor.incrementCount();
            }
        }
    }
```
上記のように、
1. HTTPリクエストの送信メソッドが呼ばれたらAttemptをインクリメント
1. HttpURLConnection.connect()が呼ばれたらConnectionをインクリメント
1. OutputStreamに実際に送信を行ったらExecutionをインクリメント

という形式でモニタリングを行った。
```plantuml
@startuml
<style>
root {
  Padding 0
  Margin 0
}
footer {
  FontColor black
  FontSize 17
}
</style>
footer 図2　実際のログ
title <img:https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636063/46043383-f7fe-e4c5-364d-57f273afae3c.png>
@enduml
```
ログを見ると、開始から3~1000msまでの間に、2003回Attemptを行っているものの、実際のコネクション開始、送信完了は5001msまで待たないと行われていなかった。JProfilerを使ってこの時のスレッドの状況をプロファイリングしたところ、Network I/Oがこの時間に行われているとわかった。

```plantuml
@startuml
<style>
root {
  Padding 0
  Margin 0
}
footer {
  FontColor black
  FontSize 22
}
</style>
footer 図3　JProfiler: Network I/Oにより、5~7秒の期間にスレッドがブロックされていることがわかる
title <img:https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636063/d151aefb-8511-c668-833f-719cfbb6b8e0.png>
@enduml
```

この間、実際に何が行われているかを調べるために、ネットワークの監視ができるツールを調べていたところ **「Wireshark」** というパケット監視ツールを見つけた。

# 3. 結論
Wiresharkは非常にユーザビリティが高く、パケット分析で非常に有用だったので、非常におすすめです。
しかしそれ以上に、こんなに大量のパケットをやり取りしている事実を見られたのは楽しかったし、TCPのハンドシェイクが実際に行われているところを確認できたのは、理論として知っているだけではわからない楽しさがありました。その点で「別に今パケット分析したいわけじゃない」っていう方にも非常におすすめです。なんならTCP/IP学んだ直後の人にはみんなこのツールを試してみてほしいくらいです。