トップページ -> 実践知識 -> パケット解析ツールとプログラミング -> Ruby/Pcap 拡張ライブラリを用いたパケットデータベースの実装例
[サイトマップへ]  

Ruby/Pcap 拡張ライブラリを用いたパケットデータベースの実装例

サイト構成 連絡先,業績など 実践知識 データの扱い コンピュータ 教材 サポートページ

TCP/IP と UDP/IP のパケットデータ(libpcap形式)をリレーショナルデータベースに格納し,集約,条件検索,CSV ファイルへのエクスポートを行う試み

【この Web ページを理解する前提となる関連事項】


前準備


概要


図.パケットデータベースの概要

libpcap 形式ファイルの例

libpcap 形式ファイルはWireshark を使いパケットをキャプチャすることで簡単に作ることができます.

Wireshark のサイトからサンプルデータをダウンロードすることも簡単です.


ソースコード

libpcap 形式のパケットデータをパケットにインポートするプログラム (Ruby プログラム)

#!/usr/bin/env ruby -wKU

require 'rubygems'
require 'sqlite3'
require 'pcap'

# SQLite3 のデータベースファイル名を DBFILENAME に設定してください.
# Windows の場合は「\\」で区切る
DBFILENAME = "/home/kaneko/pcap/examples/packetdb.sqlite3"
DBDIR = File.dirname( DBFILENAME )
DBNAME = File.basename( DBFILENAME )

# データベースオープン
Dir.chdir( DBDIR )
db = SQLite3::Database.new( DBFILENAME )

# (オプション)SQL を用いた packets テーブルの削除
sql = <<SQL
DROP TABLE tcppackets;
SQL
puts "drop table tcppackets..."
# 削除したいときは、ここの「#」を外す
#db.execute_batch(sql)

# SQL を用いた packets テーブルの定義
# id 属性は SQLite の側で自動的に連番(整数)を付ける
# その他の属性については Ruby/Pcap のドキュメントをみt欲しい
sql = <<SQL
CREATE TABLE tcppackets (
    id            INTEGER  PRIMARY KEY,
    time          REAL NOT NULL,
    size          INTEGER NOT NULL,
    tcp_data_len  INTEGER NOT NULL, 
    ip_src        INTEGER NOT NULL,
    tcp_sport     INTEGER NOT NULL,
    ip_dst        INTEGER NOT NULL,
    tcp_dport     INTEGER NOT NULL,
    tcp_flags_s   TEXT NOT NULL,
    tcp_seq       INTEGER NOT NULL );
CREATE TABLE udppackets (
    id            INTEGER  PRIMARY KEY,
    time          REAL NOT NULL,
    size          INTEGER NOT NULL,
    udp_len  INTEGER NOT NULL, 
    ip_src        INTEGER NOT NULL,
    udp_sport     INTEGER NOT NULL,
    ip_dst        INTEGER NOT NULL,
    udp_dport     INTEGER NOT NULL );  
SQL
puts "define table tcppackets..."
db.execute_batch(sql)

puts "insert values..."
# libpcap を使い libpcap 形式のファイル traffic.cap を読み込む
cap = Pcap::Capture.open_offline('traffic.cap')
cap.setfilter("ip")
cap.loop do |pkt|
  if pkt.ip? and pkt.tcp?
    db.execute( " insert into tcppackets values ( null, ?, ?, ?, ?, ?, ?, ?, ?, ? )", pkt.time.to_f, pkt.size, pkt.tcp_data_len, pkt.ip_src, pkt.tcp_sport, pkt.ip_dst, pkt.tcp_dport, pkt.tcp_flags_s, pkt.tcp_seq )
  end
  if pkt.ip? and pkt.udp?
    db.execute( " insert into udppackets values ( null, ?, ?, ?, ?, ?, ?, ? )", pkt.time.to_f, pkt.size, pkt.udp_len, pkt.ip_src, pkt.udp_sport, pkt.ip_dst, pkt.udp_dport )
  end
end
cap.close

# 問い合わせ(確認表示)
sql = <<SQL
SELECT * FROM tcppackets;
SQL
puts "query"
db.execute(sql) do |row|
    p row
end

# 問い合わせ(確認表示)
sql = <<SQL
SELECT * FROM udppackets;
SQL
puts "query"
db.execute(sql) do |row|
    p row
end

【実行手順】

  1. ソースコード中の次の2箇所を確認し,適切に書き換える

  2. ソースコードを適切なファイル名で保存し,ruby 処理系を使って実行
    ruby <ソースコードのファイル名>
    

  3. テーブルの中身が表示される(エラーメッセージが出ない)ことを確認

  4. データベースファイルが出来ていることを確認

パケットの集約の例 (SQL プログラム)

■ Source IP Address による集約の例

SELECT count(*), ip_src
FROM tcppackets
GROUP BY ip_src
ODRER BY count(*)

【実行結果の例】

SQLite コマンドライン・クライアント あるいは SQLite データベース・ブラウザ を使うのが簡単です.

SQLite コマンドライン・クライアントでは,起動時に「sqlite packetsdb.sqlite3」のようにデータベースファイル名を指定することを忘れない.

■ Source IP Address と Source TCP Portによる集約

SELECT count(*), ip_src, tcp_sport
FROM tcppackets
GROUP BY ip_src, tcp_sport
ODRER BY count(*)

【実行結果の例】

パケットの条件検索の例 (SQL プログラム)

SELECT *
FROM tcppackets
WHERE tcp_sport=3813

【実行結果の例】

CSV ファイルへのエクスポート

SQLite コマンドライン・クライアント を使うことで, CSV ファイルへのエクスポートが簡単にできます.

SQLite コマンドライン・クライアントを起動し,次のコマンドを実行する

.mode csv
.output tcppackets.csv
SELECT * FROM tcppackets;
.output stdout
.exit