flow logsをcsvとjsonに出力する

## この記事について

Suricataを使いflow logを保存するshellscriptの自分用テンプレです。あまり役に立つことが無いよう願いながら使っています。

今回は[このコード](https://qiita.com/Saito5656/items/bdeb87b04a651af2b837#demo-code-%E5%85%A8%E4%BD%93)でflow logを観察しました。


## Suricata

[「RaspberryPi 5BにSuricata7.0.3をインストール」](https://qiita.com/Saito5656/items/6cba1de67374ef2012cd)で紹介した方法で実装しています。

使い道様々でしょうが、ラズパイ4BでSuricataを使う場合は4GBRAM以上の機種をお勧めします。

## csv出力  

flow_idを含む行だけ抽出します。

```sh:suricata_csv.sh
#!/bin/bash

# 最後に処理したタイムスタンプを保存するファイル
last_timestamp_file="/tmp/last_suricata_timestamp"

# CSVファイルのパス
datetime=$(date '+%Y%m%d-%H%M%S')
CSV_FILE="Suricata_logs_${datetime}.csv"

# ファイルが存在しない場合は作成
if [ ! -f "$last_timestamp_file" ]; then
    echo "1970-01-01T00:00:00.000000+0000" > "$last_timestamp_file"
fi

# CSVファイルにヘッダーを書き込む（必要なら）
echo "timestamp,flow_log" > $CSV_FILE

# /var/log/suricata/eve.json の変更を監視
inotifywait -m -e modify /var/log/suricata/eve.json |
while read path action file; do
    # "/var/log/suricata/eve.json" の最後の行を取得
    last_line=$(tail -n 1 /var/log/suricata/eve.json)
    last_line_timestamp=$(echo "$last_line" | jq -r '.timestamp')
  
    # 最後に処理したタイムスタンプを読み込む
    last_processed_timestamp=$(cat "$last_timestamp_file")
  
    # タイムスタンプが異なる場合にのみ処理
    if [ "$last_line_timestamp" != "$last_processed_timestamp" ]; then
        if echo "$last_line" | grep -q "flow_id"; then
            # CSV行を構築
            csv_row="$last_line_timestamp,\"$(echo "$last_line" | jq -c '.')\""

            # 重複行があれば除外
            if ! grep -Fxq "$csv_row" "$CSV_FILE"; then
                echo "$csv_row" >> "$CSV_FILE"
            fi

            # 最後に処理したタイムスタンプを更新
            echo "$last_line_timestamp" > "$last_timestamp_file"
        fi
    fi
    sleep 0.2
done
```

MQTTSのログが確認できました。

<img width= 800 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/e6db1564-9b3f-5e2b-e909-82489463ce1f.png>


## json出力

jsonでも出力させます。

```sh
#!/bin/bash

THING_NAME=$(uname -n)
# MQTTのパラメータ
MQTT_HOST="127.0.0.1"
MQTT_TOPIC=${THING_NAME}_mos/${THING_NAME}_logs/suricata
echo $MQTT_TOPIC

# 最後に処理したタイムスタンプを保存するファイル
last_timestamp_file="/tmp/last_suricata_timestamp"

# ファイルが存在しない場合は作成
if [ ! -f "$last_timestamp_file" ]; then
    echo "1970-01-01T00:00:00.000000+0000" > "$last_timestamp_file"
fi

# /var/log/suricata/eve.json の変更を監視
inotifywait -m -e modify /var/log/suricata/eve.json |
while read path action file; do
    # "/var/log/suricata/eve.json" の最後の行を取得
    last_line=$(tail -n 1 /var/log/suricata/eve.json)
    last_line_timestamp=$(echo "$last_line" | jq -r '.timestamp')
  
    # 最後に処理したタイムスタンプを読み込む
    last_processed_timestamp=$(cat "$last_timestamp_file")
  
    # タイムスタンプが異なる場合にのみ処理
    if [ "$last_line_timestamp" != "$last_processed_timestamp" ]; then
        if echo "$last_line" | grep -q "flow_id"; then
            # JSON 形式でログを発行
            formatted_json=$(echo "$last_line" | jq --arg datetime "$(date "+%F %T")" '. | {datetime: $datetime, flow_log: .}')
            "${THING_NAME}_mos/${THING_NAME}_logs/suricata" -m "$formatted_json"
            # 発行したログを表示
            echo "$formatted_json"
            mosquitto_pub -h "$MQTT_HOST" -t "$MQTT_TOPIC" -m "$formatted_json"
            # 最後に処理したタイムスタンプを更新
            echo "$last_line_timestamp" > "$last_timestamp_file"
        fi
    fi
    sleep 0.5
done
```

DEMO的にlocalhostでpubsubさせました。きれいに出力できています。

```sh:pub
.
.
{
  "datetime": "2024-07-10 21:51:39",
  "flow_log": {
    "timestamp": "2024-07-10T21:51:39.388678+0900",
    "flow_id": 898199686114866,
    "in_iface": "wlan0",
    "event_type": "tls",
    "src_ip": "192.168.88.88",
    "src_port": 56307,
    "dest_ip": "52.88.88.88",
    "dest_port": 8883,
    "proto": "TCP",
    "pkt_src": "wire/pcap",
    "tls": {
      "subject": "CN=*.iot.ap-northeast-1.amazonaws.com",
      "issuerdn": "C=US, O=Amazon, CN=Amazon RSA 2048 M01",
      "serial": "xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx,
      "fingerprint": "xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx",
      "sni": "zzzzzzzzzzzzzzzzz-ats.iot.ap-northeast-1.amazonaws.com",
      "version": "TLS 1.2",
      "notbefore": "2023-12-14T00:00:00",
      "notafter": "2024-11-21T23:59:59"
    }
  }
}
.
.
```

```sh:sub
.
.
VNCcamServer1_mos/VNCcamServer1_logs/suricata {
  "datetime": "2024-07-10 21:51:39",
  "flow_log": {
    "timestamp": "2024-07-10T21:51:39.388678+0900",
    "flow_id": 898199686114866,
    "in_iface": "wlan0",
    "event_type": "tls",
    "src_ip": "192.168.88.88",
    "src_port": 56307,
    "dest_ip": "52.88.88.88",
    "dest_port": 8883,
    "proto": "TCP",
    "pkt_src": "wire/pcap",
    "tls": {
      "subject": "CN=*.iot.ap-northeast-1.amazonaws.com",
      "issuerdn": "C=US, O=Amazon, CN=Amazon RSA 2048 M01",
      "serial": "xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx,
      "fingerprint": "xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx",
      "sni": "zzzzzzzzzzzzzzzzz-ats.iot.ap-northeast-1.amazonaws.com",
      "version": "TLS 1.2",
      "notbefore": "2023-12-14T00:00:00",
      "notafter": "2024-11-21T23:59:59"
    }
  }
}  
.
.
```