rubyでパケットキャプチャツールってないのかなの思ったらQiitaの記事:PacketFuでARPリクエストのモニタリングでPacketFuを見つけたので試しに動かしてみた。
環境
- OS: Mac X 10.9.3
- Ruby: 2.2.1
- packetfu: 1.1.10
- pcaprub: 0.12.0
インストール
gemでインストール。
$ gem install packetfu pcaprub
とりあえず動かす
Qiitaの記事:PacketFuでARPリクエストのモニタリングを見る限り、ディスプレイフィルタリングを利用できるらしい。
まずは本当にキャプチャできるのかを試すために以下のサンプルスクリプトを作成してみた。
capure.rb
#!/usr/bin/env ruby
require "packetfu"
include PacketFu
def get_capture(iface,filter)
cap = Capture.new(:iface=>iface, :start=>true,
:filter=>filter)
cap.stream.each do |pkt|
puts pkt
end
end
if $0 == __FILE__
iface = ARGV[0]
filter = ARGV[1]
get_capture(iface, filter)
end
以下実行結果。
root権限がないとキャプチャはできないのでご注意を。
バイナリで何かを取得しているのがわかる。
$ sudo ruby capture.rb en0 tcp
<??^*>????E(?a-_⢟?Ӭ
??? ???U٪1P?#
>????d<??^E(?@@?l?
???????U٪1 ??@P@?J
R??^*>????Ea??K??
??W?Y??pOj???
^Ccapture.rb:9:in `each': Interrupt
from capture.rb:9:in `get_capture'
from capture.rb:19:in `<main>'
$
TCPパケットのパース
さてパケットをキャプチャをしているっぽいので次はTCPパケットをパースしてやる。
PacketFuのソースを見ると、L7以下の各種プロトコルのヘッダーは用意されていそう。
以下に時刻、SrcMac, DstMac, SrcIP, SrcPort, DestIP, DestPort
を取得するスクリプトを作成した。
capure.rb
#!/usr/bin/env ruby
require "packetfu"
include PacketFu
def get_capture(iface,filter)
cap = Capture.new(:iface=>iface, :start=>true,
:filter=>filter)
cap.stream.each do |pkt|
next unless TCPPacket.can_parse?(pkt)
t_stamp = Time.now.strftime("%Y-%m-%d %H:%M:%S.%6N")
tcp_packet = TCPPacket.parse(pkt)
src_mac = EthHeader.str2mac(tcp_packet.eth_src)
dst_mac = EthHeader.str2mac(tcp_packet.eth_dst)
src_ip = IPHeader.octet_array(tcp_packet.ip_src).join('.')
dst_ip = IPHeader.octet_array(tcp_packet.ip_dst).join('.')
src_port = tcp_packet.tcp_src
dst_port = tcp_packet.tcp_dst
puts "time:#{t_stamp},src_mac:#{src_mac},dst_mac:#{dst_mac},src_ip:#{src_ip},dst_ip:#{dst_ip},src_port:#{src_port},dst_port:#{dst_port}"
end
end
if $0 == __FILE__
iface = ARGV[0]
filter = ARGV[1]
get_capture(iface, filter)
end
簡単に説明すると、next unless TCPPacket.can_parse?(pkt)
でTCPパケット以外は読み飛ばして、TCPPacket.parse(pkt)
でTCPパケットをパースしL2->L4までの構造体にいい感じに値を格納してくれているみたい。
その後は見やすいように変換処理をしているだけ。
実行すると以下のように表示される。
$ sudo ruby capture.rb en0 tcp
time:2015-03-05 01:24:07.268786,src_mac:xx:xx:c2:d3:5e:2a,dst_mac:xx:xx:8e:98:df:64,src_ip:172.20.10.5,dst_ip:118.151.171.74,src_port:50338,dst_port:80
これは結構便利そう。