Grafana + InfluxDB でパケットフローをグラフにする

Raw Socket を利用して MAC/IP/Port ごとにカウントした結果を 5 分毎に集計した結果を InfluxDB 経由で Grafana でグラフ化してみました。


ネットワークはこんな感じ

```
Internet -----------+
                    |
              [Gateway Router]
    ここを監視---->  ||
           [L2SW (NetGear GS108E)]
               |           |
      --+------+           +---------+
        |                  |         |
    [監視ポート]          [無線AP]   [有線LAN]
```

ルータに直結したL2スイッチでルータのポートをミラーリングしキャプチャ用のポートを作成しそのポートを Raw Socket で監視しています

![total.png](https://qiita-image-store.s3.amazonaws.com/0/158961/ab62feea-eb91-062b-dd08-0e13254fe74d.png)

 - 宛先 MAC アドレスはルータ、宛先 IP はルータ以外のパケットはアップロード
 - 送信元 MAC アドレスはルータ、送信元 IP はルータ以外のパケットはダウンロード

としてそれぞれグラフにしています。
厳密に Upload/Download を出す必要がある場合は snmp などを使ってインタフェースのパケットカウンタを取得するほうが確実です。

![download.png](https://qiita-image-store.s3.amazonaws.com/0/158961/d4c5372a-bd36-2f26-8ee7-4b2e8bb9aec9.png)

MAC アドレスを取得しているので MAC 毎にどのくらい通信しているかが確認できます。
ここも 宛先 MAC, 送信元 MAC で分けることで Upload/Download を出すことができます

![chromecast.png](https://qiita-image-store.s3.amazonaws.com/0/158961/a5451e4b-2bfb-180d-6739-6fb5c1e1cbd6.png)

Grafana のグラフはグラフ下にある分類名を選択すると個別のグラフを表示することができます。

### 準備

#### 1. Ubuntu 上に必要なパッケージをインストールします。

```
sudo apt install influxdb grafana libevent-dev
```
InfluxDB は tag がサポートされている必要があるので 0.9 以降が必要です。
// tag を使わないと、書き込む形式が良くないせいで、そのまま書き込むと意図しない値が書き込まれるようです

#### 2. ミラーリングポートを監視して MAC アドレス毎にカウントできるようなデーモンを用意します
https://github.com/s-ymgch228/pktcaptd

```
% sudo pktcaptd
% sudo pktcaptdctl dump
{
    "interface" : "enp13s0f0",
    "flows" : [
        {
            "count":276,
            "size" :107596,
            "src_mac" : "00:E0:4D:10:8C:0C",
            "dst_mac" : "DC:53:60:03:DD:4C",
            "src_ip4" : "192.168.1.100",
            "dst_ip4" : "192.168.0.38",
            "l4proto" : "tcp",
            "src_port" : 22,
            "dst_port" : 59144
        },
        {
            "count":390,
            "size" :34856,
            "src_mac" : "DC:53:60:03:DD:4C",
            "dst_mac" : "00:E0:4D:10:8C:0C",
            "src_ip4" : "192.168.0.38",
            "dst_ip4" : "192.168.1.100",
            "l4proto" : "tcp",
            "src_port" : 59144,
            "dst_port" : 22
        }
    ],
    "total_flow" : 60
}
```

UNIX ドメインソケットにコマンドを書き込むと JSON 形式で出力されるのでそれをそのまま Ruby で処理することもできます

#### 3. InfluxDB を設定する
http://qiita.com/airtoxin/items/806e0bfbdecba115b3be
を参考にしつつ、パケットフローの JSON を保存するデータベースを用意します

#### 4. InfluxDB に JSON を突っ込む
Ruby を使って JSON を読み込みそのまま InfluxDB へ書き込みます
Ruby で InfluxDB のデータベースを触るために [influxdb-ruby](https://github.com/influxdata/influxdb-ruby)のモジュールをインストールしておきます

```
sudo gem install influxdb
```

influxdb-ruby の使い方

```
require 'influxdb'

DBNAME  ='pktcaptd0' #XXX set database name
DBSERVER="127.0.0.1" #XXX set database server address (default: localhost)
USERNAME="pktcaptd0" #XXX set user name of the database
PASSWORD="pktcaptd0" #XXX set password of the database

auth = {
  :username => USERNAME,
  :password => PASSWORD,
  :host     => DBSERVER,
  :port     => 8086,
  :time_precision => "s"
}

influxdb = InfluxDB::Client.new(DBNAME, auth)
values={:point_1 => 100, :point2 => 200}
tags={:type => "dummy"}
data={:values=values, :tags=tags}
influxdb.write_point('mesurement', data)

```

[pktcaptd から influxdb にデータを書き込むスクリプト](https://github.com/s-ymgch228/pktcaptd/blob/master/influxdb.rb)があるのでこれを cron などで定期的に実行する

データが書き込まれたかどうかは InfluxDB を直接アクセスして確認する
直接アクセスするときはデフォルトだと 8083 ポートに http でアクセスする
CentOS + InfluxDB v1.11 の組み合わせだと 8083 はデフォルトで使用できないようになっているので
/etc/influxdb/influxdb.conf をみて 8083 で検索をかけて近くにある enabled を true に設定する

```
[admin]
  enabled = true
  bind-address = ":8083"
```

アクセスしたら右上のデータベースを書き込んだデータベース名に変更して

```
select * from 'mesurement'
```

で検索する
検索結果を絞りたいときは where を使う

```
select * from 'mesurement' where src_ip4 = '192.168.1.100' and dst_ip4 = '192.168.0.38'
```

時間で絞りたいときは time 変数が使用できる

```
select * from 'mesurement' where time > '2017/01/01' and time < '2017/01/05'
```

#### 4. Grafana で表示する
環境によってはアイコンが見えないことがあるようなので心の目でカーソルを動かしてポインタが変わった箇所でクリックする