Splunk Stream を使わずにパケット解析したい

###対象読者
この記事はSplunkの知識がある程度ある方を対象にしています。
Splunk自体の設定の説明などは簡単に済ませています。
#Splunk Streamってなんだっけ？
Splunkでパケット解析を扱えるようにするAPPです。
これを導入することによりSplunkにてパケット解析を行えるようになります。
今回はこれを無視して自分でパケット解析の仕組みを実装します。
#なぜわざわざそんなことを？
んじゃあ素直にSplunk Stream使っておけよ。
いやいや、そうは行かない場合があるんです。
Splunk Streamを使わずにSplunkでパケット解析を行うことには複数の利点があります。
####Splunk Streamよりも軽い
Splunk Streamをデスクトップ版のSplunkで動かしてみたときに一部の人は思うでしょう。
「なんて重いAPPなんだ！」
Splunk Streamは内部でwiresharkが動いているのですが、JSONでほぼすベての情報をSplunkに取り込んでいるせいでとても鈍重なAPPになっています。私もそのせいで使うのをやめて、この記事のように自作Splunk Streamを作る事になりました。
####Splunkの容量の節約
自前で解析してからデータ取り込むことによって取り込むデータの取捨選択ができます。
極端な例ですが、流れているトラフィック量だけ見たいというときにパケット長とタイムスタンプだけSplunkに取り込めば目的が達成でき、それだけSplunkの容量が節約できるというわけです。実際、今回自宅で環境を構築したときは1ユーザーではありますが、動画を見ながらのトラフィックで2時間で100MBに行かないぐらいでした。
####パケット取得専用機器との組みあわせで10Gbps級トラフィックにも対応可能？
世の中にはパケット取得に特化したソリューションが存在します。それと並列化されたサーバー群との組み合わせで10Gbps級のトラフィックにも対応可能だと思われます。これはまだやったことないですが、いつかやってみたいですね。

#パケット解析はwiresharkに任せる。
さっきから自前で解析と散々言ってますが解析するソフトをフルスクラッチで作成するわけではありません、Splunk Streamと同じくwiresharkを使用します。今回の話はSplunkでパケットを見たいというよりもwiresharkの分析補助としてSplunkを使用するというのが発端なのでスタートラインが違うのです。
####wireshark使いから見た利点
wiresharkの拡張ソフトとして見たSplunkの利点は以下のとおりです。
#####キャプチャファイルが巨大でも一瞬で解析
wiresharkから見た利点の1つ目は、扱うパケットの量が増えてバカでかいキャプチャデータができたとしても対応可能なことです。ファイル分割すれば、取り扱えますが横断的な解析をやろうと思えばそこにはExcel地獄や、目的のパケットの抽出とファイル結合地獄という苦行が待っています。そこをSplunkに取り込めば一瞬で解析できてしまいます。たとえば10GBの分割されたキャプチャファイルが出来上がったとしても一度Splunkで取り込んでしまえば秒で解析結果を出すことができます。
#####wiresharkのBIツールとして活躍
wiresharkのグラフ化機能はお世辞にもいいとは言えません、見やすくグラフ化するにはこれまたExcel地獄が待っています。Splunkに取り込めばイケてるグラフやIPアドレスの地図上へのマッピングなんかも瞬殺できます。
######詳細解析はwiresharkで
今回の例ではSplunkは特定のよく見る解析結果を取り込んでいるためパケットの詳細解析、例えばSMBの中身を復元する等の処理はwiresharkにやってもらいましょう。Splunkで大体の時間を把握して、そのへんのパケットをwiresharkに取り込ませて解析させます。そもそもSplunkはバイナリの解析には不向きです。
wiresharkとSplunkの得意不得意を把握して運用しましょう。

#今回作成したシステムの概要
####ハードウェアとOS
宗教上の理由でOSはOpenSUSE 15.1を使います。
HWは~~一般のご家庭に必ずある~~富士通の中古サーバーを使います。
以下スペックです。
-CPU Xeon E5620 2.4GHz x 2 (8Cores)
-MEM DDR3-1066 4GB x 12 (48GB)
-Disk1 140GB x2 10000RPM RAID1 (140GB)
-Disk2 2TB x5 7400RPM RAID5 (8TB)
-NIC intelNIC 1Gbps 6Ports
-OS OpenSUSE15.1
SplunkはDisk2に展開します、インデックスも同様です。

####システム構成
システム構成は以下のようになります。
まずwiresharkで自動分割モードにてpcapファイルに保存し、その後ダンプが終ったファイルから順にwiresharkにてパケット解析を行いCSVファイルに変換、その後Splunkに投入します。
これらを自動化します。自動化と言ってもシェルスクリプトを書くだけで十分な程度です。

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535472/3116d34d-3c40-df22-3063-e7778a6321f7.png)

#パケットキャプチャ
パケットキャプチャ自体はtsharkを使用します。
以下のようにして時間ごとに分割しながら保存するようにします。

```
tshark -i eth1 -w /home/admin/trafficanalyze/pcap/test.pcapng -b duration:15
```

#wiresharkの取り扱いとSplunkに投入する情報
####厳選された解析情報
Splunkに取り込む情報を取捨選択します。一般的な情報であれば以下のような感じになるかと思います。必要であればwiresharkから情報をピックアップして追加しましょう。

```
frame.time_epoch
eth.src 
eth.dst
_ws.col.Source
_ws.col.Destination
_ws.col.Protocol
frame.protocols
frame.len
tcp.srcport
tcp.dstport
tcp.seq
tcp.ack
udp.srcport
udp.dstport
_ws.col.Info
```

####解析用のwiresharkの設定
取り込みたい情報が決定したところでそれに基づいてwiresharkのコマンドを組み立てます。今回はダンプしたpcapファイルをwiresharkのコマンドライン版である、tsharkに読ませて必要情報が前項で決めた情報を縦棒区切りのテキストファイルに変換します。
それ用にtsharkのコマンドラインオプションを弄くり倒し最終的に以下のようにします。
なお、tsharkのオプションについてはこの場では解説しません。

```
tshark -r $dir -T fields -E header=y -E separator='|' -e frame.time_epoch -e eth.src -e eth.dst -e _ws.col.Source -e _ws.col.Destination -e _ws.col.Protocol -e frame.protocols  -e frame.len -e tcp.srcport -e tcp.dstport -e udp.srcport -e udp.dstport -e _ws.col.Info > "$dir.txt"
```

####縦棒区切りの文字列からCSVへ変換
Splunkなんでこのまま投入してもいいのですが、コンマ区切りのCSVにしたほうが他のツールで扱いやすいためCSVに変換します。

```
sed -e 's/,/;/g' "$dir.txt" |  sed -e 's/|/,/g' > "$dir.csv"
```

CSVに変換したらそのままSplunkに投入します。
#####tsharkの出力時点でコンマ区切りにしない理由
wiresharkで吐き出される情報にコンマの文字が入ることがあるからです。この場合カラムの位置がぶっ壊れることは明らかです。

#Splunk側の設定とデータ投入方法
だがちょっと待ってほしい。Splunkの設定をしてないじゃないか。
ということでソースタイプの定義を書きます。
~~いつものごとくinput.confをいじります。~~
と思いましたが、input.confをいじって作るまでもなく、CSVを事前に作っておいてそれをGUIからデータ投入しソースタイプの設定する方法で十分です。

#####インデックス
今回はテストなのでデータを投入するインデックスは「wireshark」というインデックスを作ります。
####データ投入はコマンドラインで1ファイルに付き一発コマンドを叩く
データ投入は今のところsplunkのコマンドラインで1つのCSVファイルにつき1回、Splunkのデータ投入コマンドを叩いてデータを投入することにしています。しかしながら、もっと効率的な方法があるかもですね。

```
./splunk/bin/splunk add oneshot "$dir.csv" -index wireshark -sourcetype wireshark 
```

####最終的なスクリプト
最終的な自動化スクリプトは以下のようになります。

```
#!/bin/bash

tshark -i eth1 -w /home/admin/trafficanalyze/pcap/test.pcapng -b duration:15　&

while true
do
    dirs=`find ./pcap/* -maxdepth 0 -type f -name *.pcapng |sed -e '$d'|sed -e '$d'`
    for dir in $dirs;
    do
        echo $dir
        tshark -r $dir -T fields -E header=y -E separator='|' -e frame.time_epoch -e eth.src -e eth.dst -e ipv6.tclass -e ipv6.flow -e ip.dsfield -e _ws.col.Source -e _ws.col.Destination -e _ws.col.Protocol -e frame.protocols  -e frame.len -e ip.checksum -e tcp.srcport -e tcp.dstport -e tcp.seq -e tcp.ack -e tcp.checksum -e udp.srcport -e udp.dstport -e udp.checksum -e _ws.col.Info > "$dir.txt"
        sed -e 's/,/;/g' "$dir.txt" |  sed -e 's/|/,/g' > "$dir.csv"
        ./splunk/bin/splunk add oneshot "$dir.csv" -index wireshark -sourcetype wireshark 
        mv $dir ./pcapold/
        rm "$dir.csv"
        rm "$dir.txt"
    done  
    sleep 10
done
```

当然このままではtsharkがゾンビ化するのでそのへんうまくやろう！（R○nta）

#データ投入開始
すべての設定が整ったらパケット解析開始です。コマンドラインで上記のスクリプトの起動コマンドを叩いてスクリプトを起動します。以下のようにSplunkへのデータ投入が開始されます。

```
Oneshot '/home/admin/trafficanalyze/pcap/test_00627_20191202004742.pcapng.csv' added
./pcap/test_00628_20191202004757.pcapng
Running as user "root" and group "root". This could be dangerous.
Oneshot '/home/admin/trafficanalyze/pcap/test_00628_20191202004757.pcapng.csv' added
./pcap/test_00629_20191202004812.pcapng
Running as user "root" and group "root". This could be dangerous.
Oneshot '/home/admin/trafficanalyze/pcap/test_00629_20191202004812.pcapng.csv' added
./pcap/test_00630_20191202004827.pcapng
Running as user "root" and group "root". This could be dangerous.
Oneshot '/home/admin/trafficanalyze/pcap/test_00630_20191202004827.pcapng.csv' added
./pcap/test_00631_20191202004842.pcapng
Running as user "root" and group "root". This could be dangerous.
Oneshot '/home/admin/trafficanalyze/pcap/test_00631_20191202004842.pcapng.csv' added
./pcap/test_00632_20191202004857.pcapng
Running as user "root" and group "root". This could be dangerous.
Oneshot '/home/admin/trafficanalyze/pcap/test_00632_20191202004857.pcapng.csv' added
./pcap/test_00633_20191202004912.pcapng
Running as user "root" and group "root". This could be dangerous.
Oneshot '/home/admin/trafficanalyze/pcap/test_00633_20191202004912.pcapng.csv' added
./pcap/test_00634_20191202004927.pcapng
Running as user "root" and group "root". This could be dangerous.
Oneshot '/home/admin/trafficanalyze/pcap/test_00634_20191202004927.pcapng.csv' added
./pcap/test_00635_20191202004942.pcapng
Running as user "root" and group "root". This could be dangerous.
Oneshot '/home/admin/trafficanalyze/pcap/test_00635_20191202004942.pcapng.csv' added
```


#解析してみる
####トラフィック解析
タイムチャートにてトラフィックを解析します。
以下のようなサーチ文を記述します。
なおMACアドレスは自分のYAMAHAルーターのMACなので公開は控えさせていただきます。

```
index="wireshark" eth_dst="ac:44:f2:xx:xx:xx" |eval bit=frame_len*8 | timechart limit=30 per_second(bit) by ws_col_Source
```

上記のサーチ文はDownloadのトラフィックを可視化するものです。frame_lenはByte表記なのでx8にしてbitにしています。それをws_col_Sourceで分類することでどのアドレスからどれくらいDownloadされているのかわかります。下りも同じように作成し、以下のようにダッシュボードを作りました。
![TRAFFIC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535472/08142269-5517-2135-9aa7-ec9cfd88e99a.png)
(日本語と英語混じっててますが気にせずに・・・)

####ポートスキャンパケットの捕捉
セキュリティぽいことをやってみましょう。
私の環境ではプロバイダからの自動配布とはいえ、ipv4のグローバルアドレスが割り振られているので、世界中からアドレス/ポートスキャンのパケットが飛んできているでしょう。そのパケットを捕まえてどんな感じなのか見てみます。
以下のようなサーチ文を書きました。

```
index="wireshark" AND eth_dst="ac:44:f2:xx:xx:xx" AND (frame_protocols="*pppoes:ppp:ip:tcp*") | timechart limit=30 count by tcp_dstport
```
![PORTSCAN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535472/b36d0509-edbe-a3d7-f767-5ad4bd74255b.png)
う、うわ・・・1分間に3パケットぐらい来てる・・・
これはノーガードPCがいかに恐ろしいか再認識しました。

その後UDPと地図情報も追加しました。
![PORTSCAN2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535472/4572cdca-2b97-fe16-7e94-1658c60ef07b.png)


####DNSによる閲覧Webページの解析
Info情報からDNS情報を取り出し、アクセスしたページのアドレスを収集したいと思います。要はプロキシなしでプロキシログみたいなことをやるということです。DNSの情報はINFOフィールドに入っているので、それをぱぱっと分解して取り出します。

```
index="wireshark" eth_src="ac:44:f2:xx:xx:xx"| search dns |table _time ws_col_Info | eval temp=split(ws_col_Info," ")|eval Url=mvindex(temp,4) |table _time Url
```
これでプロキシ無しでアクセス解析したことあります。
十分実用になるでしょう。

![DNS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535472/7e115e94-5822-e99e-1f5d-0d46e4ccbbbb.png)

####Splunkの容量消費は1ユーザーあたり50MB/h
これを書いている間ユーチューブを再生しながら解析を続けて1時間あたりどれくらいの容量になるか計算をしました。計算の結果1ユーザーあたり50MB/hとなかなか容量が少なくなりました。普通に数GB級の通信をしてるはずですが、かなり容量が抑えられているようです。


#10Gbps級のトラフィックに耐えるには
この仕組は工夫すれば10Gbpsにも耐えるようなパケット解析基盤にすることが可能です。
####パケットキャプチャソリューションの導入
世の中にはパケットキャプチャ専用のソリューションがあります。それと組み合わせることにより10Gbpsでもロスなくパケットキャプチャすることが可能でしょう。
####解析用wiresharkの並列化
これは10Gbps化するならかなりの計算リソースが必要です。100コアで全然足りないとかそういう事態になりかねませんがAMD EPYCの2CPUなら行けるかもしれないです。パフォーマンス計測して概算しないとわかりませんね。
####40Gbps以上の高速ネットワーク
パケットキャプチャソリューションから生のpcapファイルをリアルタイムで取り出すのでそれに耐えうる高速ネットワークが必要です。InfiniBandや40Gbpsイーサネットワーク、10Gbpsｘ4のイーサネットワークなどのネットワーク構成にする必要があります。
####インデクサの並列化
これはデータを取り込む項目数によって変わります、解析用wiresharkのCPUよりは概算の計算はしやすいでしょう。
####それに耐えうるライセンス量
そもそも10Gbpsに対応させたところでライセンス料が爆発することは確実ですね、これが一番問題かもしれないです。

#まとめ
Splunk Stream使わなくてもパケット解析できた！
ポートスキャンのパケット多すぎ！
意外とログの容量が少ない。（1ユーザーあたり50MB/h）
パケット解析楽しい。