複数ノードのパケットキャプチャファイルからシーケンス図を出力するツールを作成した

# 複数ノードのパケットキャプチャファイルからシーケンス図を出力するツールを作成した

## 1. 概要

ネットワーク上の複数ノードで、Wiresharkやtcpdumpで同時にパケットキャプチャしたファイルからパケットのシーケンス図をPNG形式で出力する packetseqというツールを作成した。
言語はPython、Seqdiagというシーケンス図を作成するライブラリを使わせていただいた。

※ [GitHub](https://github.com/yusukew62/packetseq/)上にコードを上げました（2016/10/6）
※ [PyPI](https://pypi.python.org/pypi/packetseq/)に公開し、pip等でインストール、コマンド実行出来るようにしました（2016/10/10）

### 1-1. ツール作成の背景

会社でお客さん環境のネットワーク遅延の調査のため、各通信ノードで採取したパケットの突き合わせを行った。
パケットはpcap形式のためwiresharkで閲覧、はじめは複数Wiresharkを開き目で突き合わせを行ったが無理。
Wiresharkの機能にフローダイアグラムという、特定コネクションを表示するツールがあるが、複数箇所で採取したパケットの突き合わせには使えないため断念。
仕方がないのでExcel上にパケットのシーケンスを起こすことを決意。
キャプチャファイルをクライアントからの特定ポート通信に絞り、パケットをエクスポートしたあとCSV形式に変換、Excel上で手でシーケンス図を起こした。
チームで議論するには役にたったが時間がかかり過ぎたし、２度と同じことを繰り返したくないのでツールを作成した。

その時の環境（参考）
<pre>
Http Client --- Internet --- LLB --- FW --- SLB --- Http Server
</pre>

### 1-2. ツール実行に必要なもの

* Python 2.7  
* Seqdiag  
* パケットキャプチャファイル（csv形式）  
  * 下記カラムの形式となっていること
<pre>
"No.","Time","Source","Destination","Protocol","Length","Info"
</pre>
   * Timeカラムの時刻表示形式が wiresharkの時刻表示形式の"日時"形式になっていること
<pre>
日時形式(1973-06-14 01:02:03.123456）
</pre>

### 1-3. 参考にしたサイト

* [シーケンス図生成ツール seqdiag](http://blockdiag.com/ja/seqdiag/)

## 2. 流れ

### 2-1. 環境構築
1. Python2.7をインストール
<pre>
$ curl -L -O https://www.python.org/ftp/python/2.7.12/Python-2.7.12.tgz
$ tar zxvf Python-2.7.12.tgz
$ cd Python-2.7.12
$ ./configure
$ make && make altinstall
</pre>
2. pipをインストール
<pre>
$ curl -kL https://raw.github.com/pypa/pip/master/contrib/get-pip.py | python
</pre>
3. yumが使えるように修正  
yumコマンドのインタプリタを既存のPython(Version 2.6)を実行するように修正
<pre>
$ vi /usr/bin/yum
例）下記のとおり修正
#!/usr/bin/python2.6
</pre>
4. 作成したツールの準備  
  - コマンド化して使う場合
<pre>
$ pip install packetseq
</pre>
  - プログラムのみ使う場合  
[packetseq.py](https://github.com/yusukew62/packetseq/blob/master/packetseq/packetseq.py)を実行する環境に保存する

### 2-2. 使用手順（概要）  

1. 通信経路箇所でパケットキャプチャ
2. キャプチャファイルから特定ポートの通信のみエクスポート
3. csvファイルとして保存
4. 今回作成したツール実行環境上にcsvファイルを送信
5. ツールを実行
6. 標準入力から通信間の対向機器の名称を入力
7. シーケンス図が作成

### 2-3. 使用手順（説明）  

今回は下記の環境をもとに使い方を説明
<pre>
Client(Windows 7) --- Proxy(Squid) --- Server(nifty.comなど)
</pre>

1. 通信経路箇所でパケットキャプチャ  
Client(Windows 7)上ではwireshark、Proxy(Squid)上ではtcpdumpを使用した  
例）クライアント上でのパケットキャプチャ
<pre>
wiresharkを実行し、通信が終了したら保存する
ファイル名は任意、client.pcapとして保存
</pre>
例）プロキシサーバ上でのパケットキャプチャ
<pre>
$ tcpdump -i eth1 -w proxy.pcap
ファイル名は任意、proxy.pcapとして保存
</pre>
2. キャプチャファイルから特定ポートの通信のみエクスポート  
先ほどキャプチャしたファイルをwiresharkで開き特定ポートに絞る  
具体的には、3way handshakeのSYNフラグを送っている際のポート番号を確認  
wireshark上でフィルタを行う  
<pre>
tcp.port==ポート番号
</pre>
3. csvファイルとして保存  
wiresharkでcsv形式で保存する  
例）クライアント上でのパケットキャプチャ  
<pre>
ファイル名は任意、client.csvとして保存  
</pre>
例）プロキシサーバ上でのパケットキャプチャ
<pre>
ファイル名は任意、proxy.csvとして保存
</pre>
4. 今回作成したツール実行環境上にcsvファイルを送信  
5. ツールを実行  
今回は採取箇所が２箇所なので先ほどキャプチャしたファイルをクライアント側から近い順に引数として２ファイル渡して実行  
  - pip等からインストールしてコマンドから使用する場合
<pre>
$ packetseq client.csv proxy.csv
</pre>
  - 保存した packetseq.pyから実行する場合
<pre>
$ python packetseq.py client.csv proxy.csv 
</pre>
6. 標準入力から通信間の対向機器の名称を入力  
ファイルごとに source-ip と destination-ip の２回、名前を入れるよう標準入力で入力を求められる  
下記の例はクライアントープロキシ間なので、"Client"と"Proxy"とした  
<pre>
\########################################
file_name:client.csv
\########################################
src ip:192.168.1.3 -> src name: ???
input src name > Client （★標準入力）
dst ip:192.168.1.62 -> dst name: ???
input dst name > Proxy （★標準入力）
</pre>
続いてプロキシサーバ間も入力も求められるので、"Proxy"と"Sever"とした  
<pre>
\########################################
file_name:proxy.csv
\########################################
src ip:192.168.1.3 -> src name: ???
input src name > Proxy （★標準入力）
dst ip:192.168.1.62 -> dst name: ???
input dst name > Server （★標準入力）
</pre>
7. シーケンス図が作成  
out.png と out.diag というファイルが作成される  
out.pngがPNG形式のシーケンス図  
out.diagが画像生成の元となったSeqdiag形式のファイル  
<pre>
$ file out.*
out.diag: ASCII text, with very long lines
out.png:  PNG image data, 1856 x 31706, 8-bit/color RGBA, non-interlaced
</pre>
左から"Client", "Proxy", "Web"のシーケンス図となっている  
![packetseq_img.png](https://qiita-image-store.s3.amazonaws.com/0/43280/72478d85-e831-ca3d-f19e-2e8d7d60a6d0.png)  
これなら複数箇所のパケットのシーケンスがわかる  

## 3. ツールについて

### 3-1. ソースコード
[packetseq.py](https://github.com/yusukew62/packetseq/blob/master/packetseq/packetseq.py) を参照

### 3-2. 処理の流れ

1. 引数でcsvファイルを渡す
2. ファイルごとにSYNフラグから通信間を検出
3. 2の対向ノードの名前を標準入力で渡す
4. IPアドレスから3で指定した名前に置換
5. Seqdiag形式に出力
6. Seqdiagに渡して画像を出力

### 3-3. オプション

|オプション|説明|備考|
|---|---|---|---|
|-h, --help|ヘルプメッセージを表示|-|
|-o, --out 出力ファイル名|出力先ファイル名を指定|-|
|-i, --info 出力タイプ|シーケンス上のパケット情報の出力を選択|出力タイプは、summary, info, defaultの3つから選択|
|-t, --type|出力形式をpngかsvgを選択|-|

### 3-4. 色指定

[cssの色キーワード](https://developer.mozilla.org/ja/docs/Web/CSS/color_value)指定可能
例）ソースコード上での指定  

|tcp flag|color|
|---|---|
|SYN|blue|
|SYN ACK|red|
|ACK|green|
|FIN|navy|
|FIN ACK|maroon|
|RST|purple|
|RST ACK|fuchsia|
|URG|olive|
|PSH|orange|
|Other|gray|
            
色設定は\__init__関数のself.color_dict内で指定する
<pre>
        # 色情報の辞書
        self.color_dict = {
            'SYN': "blue", 'SYN ACK': "red",
            'ACK': "green",
            'FIN': "navy", 'FIN ACK': "maroon",
            'RST': "purple", 'RST ACK': "fuchsia",
            'URG': "olive", 'PSH': "orange",
            'Other': "gray",
        }
</pre>

### 3-5. パケット情報の出力
1. "summary"
tcpフラグと送信データのみ
![summary.png](https://qiita-image-store.s3.amazonaws.com/0/43280/92b865b4-4f9f-cc22-bf36-3a8fa8a35a27.png)
2. "info"
infoデータ全表示
![info.png](https://qiita-image-store.s3.amazonaws.com/0/43280/986b1e03-8652-1d6a-157b-d18f47a1ddb3.png)
3. "default"
sportとdportを削除
![default.png](https://qiita-image-store.s3.amazonaws.com/0/43280/fdd0ef4f-967c-9f6d-b04a-0d6089c1fd02.png)


## 4. 課題

* 時間を見やすくして、どこで遅延が起きているかわかりやすくしたい
* パケットの対応を見やすくして、送信データと対応しているACKを紐付けたい
* 色指定などハードコーディングしている箇所をコンフィグファイルから指定できるようにする

## 5. 注意

* 時間でソートしているため、時間がずれていると正しいシーケンス図とならない（当たり前だが）
* シーケンス図作成環境上のフォント（？）によって、パケット情報の文字表示が若干崩れることがある（調査中）