2023年3月19日日曜日

ネットワークログの分析1 : ネットワークログの取得と分析準備

 ネットワークログは様々なものがありますが、オープンデータで入手できるものを使って、分析をしてみようと思います。ここでは以下の点に注目して実施していきます。プログラム言語はPythonでやっていきます。

(1)大量なログを分析できる形に整えることができる

(2)ネットワーク管理者が設計図で確認できる内容ではなく、実際のネットワークデータから、コンピュータ間の同値類(セグメントみたいなもの)を確認し、可視化する

(3)コンピュータ間の通信をマルコフ連鎖でモデル化する(推移確率を求める)

1. 利用データの準備

今回は「Unified Host and Network Data Set」を使わせてもらいます。ここには「Network Event Data」と「Host Event Data」の2つがあり、今回は「Network Event Data」を使います。このデータは、サイトから引用すると下記のような項目があり、シンプルでわかりやすいです。

利用するためには、メールアドレスの登録をすると、データをダウンロードするためのスクリプトが出てくるので、Linux等の環境で行い、ダウンロードを行なって下さい。ただし、データが巨大なので十分な領域を確保してやりましょう。解凍後のcsvの1ファイルは7~10Gbyte位あります。あと謝辞にこのサイトを入れるのを忘れないようにしましょう。
M. Turcotte, A. Kent and C. Hash, “Unified Host and Network Data Set”, in Data Science for Cyber-Security. November 2018, 1-22

ダウンロードしたら、展開しておき、csvファイルを確認します。今回は最初の日のデータで、「netflow_day-02.bz2」(1.08GB)を展開した「netflow_day-02.csv」(7.15GB)を使っていきます。

bz2の展開には「bunzip2 netflow_day-XX.bz2」のようにbunzip2を使うといいでしょう。

2. データの取り込み

必要なモジュール(numpy, pandas, matplotlib.pyplot)をインストールして、ファイルを取り込みます。

#https://csr.lanl.gov/data/2017/
file = './netflow_day-02.csv'
df = pd.read_csv(file, header=None)
df.columns = ['Time','Duration','SrcDevice','DstDevice','Protocol','SrcPort','DstPort','SrcPackets','DstPackets','SrcBytes','DstBytes']
df
view raw gistfile1.txt hosted with ❤ by GitHub

無事データの取り込みができると、このファイルでは、115,949,436件のデータがあることがわかります。
基本統計情報を見てみると、特にバイト数が桁数が大きいところがあるので、他の項目もまとめて10^6で割り、バイトはメガバイト(MB)に変換しておきます。maxの項目をみると、桁数が減っていることがわかります。
変更前のdf.describe()
10^6で割った後のdf.describe()

3. デバイス集合を作成
「SrcDevice」と「DstDevice」を使って、デバイス集合を作成します。このデバイス集合を使って、どこからどこへの通信があるかを集計していきます。SrcDeviceにしかないデバイス、DstDeviceにしかないデバイス、両方にあるデバイスがあるので、それぞれ集合として抽出して、その和集合を取ります。SrcDeviceには25,847件、DstDeviceには25,308件ありました。
SrcDevice_list = df['SrcDevice'].unique().tolist()
print(len(SrcDevice_list))
SrcDevice_df = pd.DataFrame({'SrcDevice': SrcDevice_list})
SrcDevice_df.to_csv('netflow_day-02_srcdevice.csv', index=False)
DstDevice_list = df['DstDevice'].unique().tolist()
print(len(DstDevice_list))
DstDevice_df = pd.DataFrame({'DstDevice': DstDevice_list})
DstDevice_df.to_csv('netflow_day-02_dstdevice.csv', index=False)
#和集合を求める
SrcDevice_set = set(SrcDevice_list)
DstDevice_set = set(DstDevice_list)
Device_set = SrcDevice_set | DstDevice_set
Device_list = list(Device_set)
Device_df = pd.DataFrame({'Device': Device_list})
Device_df.to_csv('netflow_day-02_device.csv', index=False)
#積集合を求める(追加 2023/05/02)
Device_set_intersection = SrcDevice_set & DstDevice_set
Device_list_intersection = list(Device_set_intersection)
Device_df_intersection = pd.DataFrame({'Device': Device_list_intersection})
Device_df_intersection.to_csv(file + '_device_intersection.csv', index=False)
view raw gistfile1.txt hosted with ❤ by GitHub

[2023/05/02]修正
ここで書いてあるように、最初はデバイスの和集合でやっていました。取りこぼしが無いように、全てのデバイスで集計して、通信が無いデバイスを後から削除しようと思いましたが、実際やってみると、集計ファイルが100GBになり、とても無理でした。ですので、和集合ではなく、積集合をとり、From <--> To の通信が両方ともあるデバイスのみ対象に変更しました。

4. 推移表の作成
3で作成したデバイス集合を使って、どのデバイスからどのデバイスへ通信があったかを集計します。今回はデータフレームの抽出は使わず、groupbyを使うことで高速に処理できます。

#ファイルを分割せずに、集約して出力する
#PC間の通信回数を抽出
device_weight = []
from_device = []
to_device = []
from_packets = []
to_packets = []
from_bytes = []
to_bytes = []
duration = []
start = time.time()
index = 1
for src, sub_df in df.groupby('SrcDevice'):
for dst, subsub_df in sub_df.groupby('DstDevice'):
from_device.append(src)
to_device.append(dst)
cnt = len(subsub_df)
device_weight.append(cnt)
from_packets.append(subsub_df['SrcPackets'].sum())
to_packets.append(subsub_df['DstPackets'].sum())
from_bytes.append(subsub_df['SrcBytes'].sum())
to_bytes.append(subsub_df['DstBytes'].sum())
duration.append(subsub_df['Duration'].sum())
print('{0} %完了'.format(index / len(SrcDevice_list) * 100))
index += 1
# if index > 30:
# break
df_sum = pd.DataFrame({'from': from_device, 'to': to_device, 'count' : device_weight, 'duration': duration, 'from_packets': from_packets, 'to_packets': to_packets, 'from_bytes': from_bytes, 'to_bytes': to_bytes})
df_sum.to_csv('netflow_day-02_sum.csv')
elapsed_time = time.time() - start
print ("calclation_time:{0}".format(elapsed_time) + "[sec]")
df_sum
view raw gistfile1.txt hosted with ❤ by GitHub

0 件のコメント:

コメントを投稿