RubyでTCP/IPパケットキャプチャ
プログラミング言語Rubyは,プログラムを書いていて気持ちが良い,実にハッカー向きの言語だと思います.
なので,ハッカーが色々なライブラリを開発し続けてくれて,どんどん便利になっています.
一例として,今や生活に欠かせないインターネットの,通信内容を調べるプログラムを書きたくなった場合に便利なライブラリの一つにパケットキャプチャライブラリ「Pcap」があります.
http://www.goto.info.waseda.ac.jp/~fukusima/ruby/pcap-j.html
Ruby/Pcap 拡張ライブラリ
Ruby から LBL の Packet Capture Library を使うための拡張ライブラリです。TCP/IPのヘッダの情報にアクセスするためのクラスも含んでいます。
C 言語から直接 pcap を使うよりはずっと楽にプログラムが書けます。例えば tcpdump もどきのプログラムはこれだけで書けます。
tcpdumpはTCPプロトコルで通信されている内容の解析に使われます.
私は,tcpdumpよりも上位レイヤー的で使い易いtcpflowをよく使います.
tcpflow -- TCP Flow Recorder
What is tcpflow?
tcpflow is a program that captures data transmitted as part of TCP connections (flows), and stores the data in a way that is convenient for protocol analysis or debugging. A program like 'tcpdump' shows a summary of packets seen on the wire, but usually doesn't store the data that's actually being transmitted. In contrast, tcpflow reconstructs the actual data streams and stores each flow in a separate file for later analysis.
(適当な抄訳)
tcpdumpはTCPプロトコルの細かい振る舞いを記録してくれるが,実際に流れている通信内容を記録してくれない.tcpflowは,ネットワーク上を流れるTCPのデータ内容を記録する.
話は戻りましてPcapですが,「例えば tcpdump もどきのプログラムはこれだけで書けます。」とリンクが張られております.その内容は,次のようなものです.
#!/usr/local/bin/ruby require 'pcaplet' include Pcap class Time # tcpdump style format def to_s sprintf "%0.2d:%0.2d:%0.2d.%0.6d", hour, min, sec, tv_usec end end pcaplet = Pcaplet.new pcaplet.each_packet { |pkt| print "#{pkt.time} #{pkt}" if pkt.tcp? print " (#{pkt.tcp_data_len})" print " ack #{pkt.tcp_ack}" if pkt.tcp_ack? print " win #{pkt.tcp_win}" end if pkt.ip? print " (DF)" if pkt.ip_df? end print "\n" } pcaplet.close
僅か25行です.Rubyの強力さが分かるというものです.
例えば,Webサーバをポート80で運営しており,その内容を監視したいとしましょう.すると,次のようなプログラムで通信内容を見ることができます.
#!/usr/bin/ruby require 'pcap' def capture_data(interval) capdat = []; i = 0; pcaplet = Pcap::Capture.open_live("eth0", 1460,true,1000); access = Pcap::Filter.new('tcp and dst port 80',pcaplet); pcaplet.setfilter(access); pcaplet.each_packet { |pkt| if pkt.tcp_data_len>0 then p pkt.tcp_data; i += 1; end; break if i>interval; } pcaplet.close end; capture_data(10);
プログラム中の「eth0」は,ifconfigで出るネットワークカード名に変更して下さい.
このプログラムを実行すると,Webサーバにアクセスが来ると,次のように表示されます.
"GET /index.html HTTP/1.1\r\nAccept: */*\r\nAccept-Language: ja\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)\r\nHost: www.example.jp\r\nConnection: Keep-Alive\r\n\r\n"
TCPプロトコル上で,HTTPプロトコルの通信が来ていることが分かります.
便利なものです.
このサンプルは10パケット受信すると止まってしまいます.パケット数を増減させるには,capture_data(10)の「10」の値を変えて下さい.