HOME会社概況業務内容開発分野開発事例CANモジュールソフテックだよりお問い合わせ
HOME > ソフテックだより > 第269号(2016年11月2日発行) 技術レポート「Wiresharkの活用法 その2 〜専用プロトコルを表示させる〜」

「ソフテックだより」では、ソフトウェア開発に関する情報や開発現場における社員の取り組みなどを定期的にお知らせしています。
さまざまなテーマを取り上げていますので、他のソフテックだよりも、ぜひご覧下さい。

ソフテックだより(発行日順)のページへ
ソフテックだより(技術分野別)のページへ
ソフテックだより(シーン別)のページへ


ソフテックだより 第269号(2016年11月2日発行)

技術レポート

「Wiresharkの活用法 その2 〜専用プロトコルを表示させる〜」

1. はじめに

技術レポート第213号「Wiresharkの活用法 〜長時間モニタリングとデータ解析について〜」ではWireshark(ワイヤーシャーク)を接続する方法とデータ解析する方法をお伝えしていました。 今回はWiresharkでサポートされていないプロトコルを表示する方法をお伝えしたいと思います。

ソフテックはEthernetを用いて通信するソフトをパソコン・マイコン・PLC問わず開発しています。そのプロトコルの多くは開発するシステムだけで使われる専用のプロトコルです。
しかしそのパケットをWiresharkで見ると連続した1行のバイト列で表示されるだけとなるため把握しづらいです。

今回は仮想のプロトコル「SOFTECHプロトコル」のパケットを意味がある単位でWiresharkに表示させるという内容で説明します。
なお、使用するWireshark はVersion 2.2.1とします。本稿執筆時点(2016年10月17日)で最新です。

2. SOFTECHプロトコルについて

仮想のプロトコル「SOFTECHプロトコル」は以下の仕様とします。

  • TCPプロトコルの上位プロトコル。
  • サーバーのポート番号が40000。
  • パケットは「ヘッダー」と「その他データ」で構成する。図1参照。
  • 「その他データ」はヘッダーの「種別コード」によって内容が変わる。

パケットのフィールド構成(フィールド名とバイト数)
図1. パケットのフィールド構成(フィールド名とバイト数)

今回は「ヘッダー」をフィールドに分けて表示させるようにします。
「その他データ」は1行で表示させます。
次から実際の作業を説明します。

3. 実際の作業内容

それでは実際の作業内容を説明します。
作業はWireshark設定ファイルの編集とSOFTECHプロトコル表示設定ファイルの作成となります。ファイルの作成が終わったらWiresharkを起動して表示を確認します。

3.1 Wiresharkの設定ファイル「init.lua」を編集する

「init.lua」はWiresharkがインストールされたフォルダにあります。
これを開いて下表のとおり3箇所を編集します。
これにより次章で説明するSOFTECHプロトコルの表示内容を設定したファイル「SOFTECH.LUA」が読み込まれるようになります。

    
No. 変更内容 説明
1 disable_lua = false “disable_lua”を検索して“false”でない場合には“false”に変更します。
2 run_user_scripts_when_superuser = true “run_user_scripts_when_superuser”を検索して“true”に変更します。
3 dofile("SOFTECH.LUA") 専用プロトコルを定義したファイル名(SOFTECH.LUAとします)を一番最後の行に追加します。 複数のLUAファイルの定義も可能です。

表1. 「init.lua」ファイルの編集内容

3.2 「SOFTECH.LUA」ファイルを作る

パケットの表示内容を設定するテキストファイル「SOFTECH.LUA」を新規作成します。
作ったファイルは「init.lua」と同じくWiresharkがインストールされたフォルダに保存します。

3.2.1 ファイルの構成

テキストエディタで新規作成したファイルに下記(1)〜(5)を記述します。

(1)
プロトコルの名前をつけます。(今回は“SOFTECH”と“SOFTECH Protocol”)
(2)
パケットを独自に表示させるための関数を宣言します。
(3)
メイン画面のProtocol列に表示させる名称を設定します。(今回は“SOFTECH”)
(4)
パケットを意味のある単位(今回はフィールド単位)でツリー表示させるプロトコルツリーを定義します。
受信データが入った配列(下記ではbuffer)のどこから何バイトを表示させるかで定義します。
(5)
TCPまたはUDPポート番号と@のプロトコルを紐付けしてWiresharkへ登録します。

3.2.2 「SOFTECH.LUA」の内容

「SOFTECH.LUA」ファイルを示します。
上記(1)〜(5)との対応をコメント行(“--”で始まる行)で入れましたのでご確認下さい。
(4)ではヘッダーをフィールド単位に表示させる処理とその他データを1行で表示させる処理を記述しています。実際の表示結果の図3を参照してみて下さい。

-- (1)「SOFTECHプロトコル」の名前を宣言する。プロトコルを選択するときに表示される。
Softech_proto = Proto("SOFTECH", "SOFTECH Protocol")

-- (2)パケットをフィールド単位表示にする関数の宣言。
-- bufferにSOFTECHプロトコルの受信データが入る。
function Softech_proto.dissector(buffer, pinfo, tree)

 -- (3)メイン画面のProtocol列に"SOFTECH"を表示する。
 pinfo.cols.protocol = "SOFTECH"

 -- (4)ここからプロトコルツリーにフィールド単位の表示をする処理
 -- プロトコルツリーに"SOFTECH Protocol Data"を追加する
 subtree = tree:add(Softech_proto, buffer(), "SOFTECH Protocol Data")

 -- "SOFTECH Protocol Data"にプロトコルツリー"Header"を追加する。
 -- 表示対象はbuffer[0]から12バイト分。
 subtree2 = subtree:add(buffer(0,12), "Header")
 -- "Header"に各フィールドを追加する。
 --   "1.Flame Length:"の後にbuffer[0]から2バイト分表示させる。
 subtree2:add(buffer(0,2), "1.Flame Length:" .. buffer(0,2):uint())
 --   "2.Sorce ID:"の後にbuffer[2]から1バイト分表示させる。
 subtree2:add(buffer(2,1), "2.Sorce ID:" .. buffer(2,1):uint())
 subtree2:add(buffer(3,1), "3.Spare:" .. buffer(3,1):uint())
 subtree2:add(buffer(4,1), "4.Dest ID:" .. buffer(4,1):uint())
 subtree2:add(buffer(5,1), "5.Spare:" .. buffer(5,1):uint())
 subtree2:add(buffer(6,1), "6.Kind Code:" .. buffer(6,1):uint())
 subtree2:add(buffer(7,1), "7.Flame No:" .. buffer(7,1):uint())

 -- "Header"プロトコルツリーに"8.DateTime"を追加する
 -- 表示対象はbuffer[8]から4バイト分。
 subtree3 = subtree2:add(buffer(8,4), "8.DateTime")
 -- "8.DateTime"に各フィールドを追加する
 --   "8.1.Day:"の後にbuffer[8]から1バイト分表示させる。
 subtree3:add(buffer(8,1), "8.1.Day:" .. buffer(8,1):uint())
 subtree3:add(buffer(9,1), "8.2.Hour:" .. buffer(9,1):uint())
 subtree3:add(buffer(10,1),"8.3.Min:" .. buffer(10,1):uint())
 subtree3:add(buffer(11,1),"8.4.Sec:" .. buffer(11,1):uint())

 -- 「その他データ」があるか調べる。ある場合は1行で表示する。
 -- 受信データ長からヘッダー長12を引いてdatalenに入れる
 local datalen = buffer:len() - 12
 -- datalenが0より大きいか?
 if datalen > 0 then
  -- "SOFTECH Protocol Data"に"Kind-specific Data"を追加する
  subtree2 = subtree:add(buffer(12,datalen), "Kind-specific Data" )
  -- "Data"の後にbuffer[12]からdatalenバイト分表示させる。
  subtree2:add(buffer(12,datalen), "Data:" .. buffer(12,datalen))
 end
end

-- (5)TCPポート40000とSOFTECHプロトコルを紐付けしてWiresharkへ登録する。
DissectorTable.get("tcp.port"):add(40000, Softech_proto)

作業は以上です。あとはWiresharkを起動して記述したとおり表示されるかどうかを確認します。

3.3 Wiresharkを起動して確認する

Wiresharkを起動して通信を開始します。

3.3.1 LUAファイルが正常な場合

下図2右側の青枠・緑枠のように表示されます。(左側は標準の表示)
パケット表示画面(図3)を開いてLUAファイルに記述したとおりになっていることを確認します。
なお、左側の青枠は「SOFTECH.LUA」の(4)による表示、緑枠は(1)(3)(5)による表示になります。

Wireshark標準の表示(左)と「SOFTECH.LUA」(右)対応後の表示
図2. Wireshark標準の表示(左)と「SOFTECH.LUA」(右)対応後の表示

パケット表示画面でSOFTECHプロトコルのパケットを表示
図3. パケット表示画面でSOFTECHプロトコルのパケットを表示

3.3.2 LUAファイルに問題がある場合

この場合はWiresharkの起動直後にエラー画面が表示されます。
下図4は「SOFTECH.LUA」の2行目にエラーがあることを示しています。
LUAファイルを修正して再起動します。

Wireshark起動時に表示されるLUAファイルエラー
図4. Wireshark起動時に表示されるLUAファイルエラー

(2行目“= Proto”の“o”を抜いて“= Prot”にしたファイルで起動したときのエラー表示)

3.3.3 LUAファイルによるその他の効果→表示の絞り込み

表示フィルターへ「softech」と入力すると下図5のようにSOFTECHプロトコルだけが表示されるようになります。(下図赤枠)

SOFTECHプロトコルの絞り込み表示
図5. SOFTECHプロトコルの絞り込み表示

また表示フィルターに「Tcp.port==40000」(SOFTECHプロトコルと紐付けたポート番号)を入力するとSOFTECHプロトコルに加えてSYN、ACKなどTCPレベルのパケットを表示出来ます。(下図6オレンジ枠)
これはLUAファイルの効果ではありませんがLUAファイルがあることでProtocol列にTCPとSOFTECHが区別されて表示されます。LUAファイルが無いとすべてTCPと表示されます。

ポート40000の絞り込み表示
図6. ポート40000の絞り込み表示

4. おわりに

自分たちが手がけたプロトコルがWiresharkで解析されて表示されるのを見ると、わかり易くなるだけではなくしっかり情報を通知しあっているな、間違ったデータを送ったな、などと愛着が湧いてくるのを感じます。
今回はそのような気持ちで書きました。
参考にして頂ければ幸いです。

なお、記述にはLUAというスクリプト言語が使われています。
LUAをもっと駆使すればパケットをより分かり易く表示させることが出来ますので以下にリンクを載せます。興味のある方は参考にして下さい。
またWiersharkのAPIの詳細へのURLも載せます。APIを駆使すればさらにWiresharkの機能を引き出すことが出来ますので参考にして下さい。

LUAスクリプト言語リファレンスマニュアル
http://www.lua.org/
WiresharkのLUAサポートについて
https://www.wireshark.org/docs/wsdg_html_chunked/wsluarm.html
WiresharkのAPIリファレンスマニュアル
https://www.wireshark.org/docs/wsdg_html_chunked/wsluarm_modules.html

(N.K.)


関連ページへのリンク

関連するソフテックだより