tremaでL7データのダンプを取る
»
Tremaで書いてみました。L7データのダンプを取るコードです。やはり、L7エンジニアとしてはこれが最初のステップかなと思います。
ちょっと融通が利かないですが、とりあえずということで
- レイヤー2ヘッダ長:14バイト
- レイヤー3ヘッダ長:20バイト
- レイヤー3ヘッダ長:32バイト
と、今回は固定してしまいました。本格的にするのであればL3とL4のヘッダ長を見る必要がありますが……。
■■■ 構成図 ■■■
Ubuntu Client (curlをHTTPクライアントとする) eth1 192.168.1.141 | | eth1 192.168.1.136 Ubuntu Server (ApacheをHTTPサーバとする) (OpenFlow コントロールパスとデータパスが両方動作中)
■■■ 動かしてみた結果 ■■■
Ubuntu Client。こちらは普通に、何の変哲もないHTTP通信です。
root@ubuntu141:~# curl 192.168.1.136 <html><body><h1>It works!</h1> <p>This is the default web page for this server.</p> <p>The web server software is running but no content has been added, yet.</p> </body></html> root@ubuntu141:~#
Ubuntu Server。こちらでtremaを動かしています。
root@ubuntu136:/home/hiro/test/trema# trema run l7_dump.rb -c learning-switch2.conf sudo: unable to resolve host ubuntu136 Switch 0x136 is UP packet_in. dp: 0x136, in_port: 1 L2 hex: 005056a062a9005056a073000800 L3 hex: 450000d8ffd340004006b5e6c0a8018dc0a80188 L4 hex: e2610050ae66ff3f6e399418801807219d4e00000101080a003a00ef0039b0dc L7 hex: 474554202f20485454502f312e310d0a557365722d4167656e743a206375726c2f372e32312e362028693638362d70632d6c696e75782d676e7529206c69626375726c2f372e32312e36204f70656e53534c2f312e302e3065207a6c69622f312e322e332e34206c696269646e2f312e3232206c696272746d702f322e330d0a486f73743a203139322e3136382e312e3133360d0a4163636570743a202a2f2a0d0a0d0a L7 data: GET / HTTP/1.1 User-Agent: curl/7.21.6 (i686-pc-linux-gnu) libcurl/7.21.6 OpenSSL/1.0.0e zlib/1.2.3.4 libidn/1.22 librtmp/2.3 Host: 192.168.1.136 Accept: */* packet_in. dp: 0x136, in_port: 1 L2 hex: 005056a07300005056a062a90800 L3 hex: 4500020024c5400040068fcdc0a80188c0a8018d L4 hex: 0050e2616e399418ae66ffe38018079836dc00000101080a0039b0dc003a00ef L7 hex: 485454502f312e3120323030204f4b0d0a446174653a205765642c203239204d617920323031332031313a31393a333420474d540d0a5365727665723a204170616368652f322e322e323020285562756e7475290d0a4c6173742d4d6f6469666965643a204d6f6e2c2030312041707220323031332030313a35313a313020474d540d0a455461673a202236306130662d62312d34643934326461653665326631220d0a4163636570742d52616e6765733a2062797465730d0a436f6e74656e742d4c656e6774683a203137370d0a566172793a204163636570742d456e636f64696e670d0a436f6e74656e742d547970653a20746578742f68746d6c0d0a582d5061643a2061766f69642062726f77736572206275670d0a0d0a3c68746d6c3e3c626f64793e3c68313e497420776f726b73213c2f68313e0a3c703e54686973206973207468652064656661756c7420776562207061676520666f722074686973207365727665722e3c2f703e0a3c703e546865207765622073657276657220736f6674776172652069732072756e6e696e6720627574206e6f20636f6e74656e7420686173206265656e2061646465642c207965742e3c2f703e0a3c2f626f64793e3c2f68746d6c3e0a L7 data: HTTP/1.1 200 OK Date: Wed, 29 May 2013 11:19:34 GMT Server: Apache/2.2.20 (Ubuntu) Last-Modified: Mon, 01 Apr 2013 01:51:10 GMT ETag: "60a0f-b1-4d942dae6e2f1" Accept-Ranges: bytes Content-Length: 177 Vary: Accept-Encoding Content-Type: text/html X-Pad: avoid browser bug <html><body><h1>It works!</h1> <p>This is the default web page for this server.</p> <p>The web server software is running but no content has been added, yet.</p> </body></html> ^C terminated root@ubuntu136:/home/hiro/test/trema#
一旦L2~L7までそれぞれのレイヤーに分けて16進数表示をした上で、その後にL7だけhex →ascii変換してデータを表示させています。
- 「L7 hex」という項目でTCPデータの16進数表示をしています
- 「L7 data」という項目で、TCPデータのascii表示をしています。
2つパケットがあり、一つは「GET / HTTP/1.1」を含むHTTPリクエスト、もう一つは「HTTP/1.1 200 OK」を含むHTTPレスポンスであることが分かると思います。
■■■ 設定・ソース ■■■
設定とソースはこちらです。よければお使い下さい。
root@ubuntu136:/home/hiro/test/trema# cat learning-switch2.conf vswitch("lsw") { datapath_id "0x136" ip "192.168.1.136" } link "lsw", "eth1" link "lsw", "eth2" root@ubuntu136:/home/hiro/test/trema# cat l7_dump.rb class LearningSwitch < Controller def start @fdb = {} end def switch_ready datapath_id info "Switch #{ datapath_id.to_hex } is UP" end def switch_disconnected( datapath_id ) info "Switch #{ datapath_id.to_hex } is DOWN" end def packet_in( datapath_id, message ) if !message.tcp? return end l7_dump datapath_id, message return end private def l7_dump( datapath_id, message ) msg_data_s = message.data.unpack("H*").to_s; l2_hdr = 14 l3_hdr = 20 l4_hdr = 32 l4_tot_len = (l2_hdr + l3_hdr + l4_hdr)*2 #info "total_len: " + message.total_len.to_s if message.total_len > l4_tot_len #info msg_data_s.slice(l4_tot_len..-1) else return end info "packet_in. dp: " + datapath_id.to_hex + ", in_port: " + message.in_port.to_s info "L2 hex: " + msg_data_s.slice(0,l2_hdr*2) info "L3 hex: " + msg_data_s.slice(l2_hdr*2, l3_hdr*2) info "L4 hex: " + msg_data_s.slice((l2_hdr + l3_hdr)*2, l4_hdr*2) l7_hex = msg_data_s.slice(l4_tot_len..-1) info "L7 hex: " + l7_hex l7_data = "" @l7_two_char = l7_hex.unpack("a2"*(l7_hex.length/2)) @l7_two_char.each do | each | #info sprintf("%c", each.hex) l7_data << sprintf("%c", each.hex) end info "L7 data: " + l7_data + "\n" end end root@ubuntu136:/home/hiro/test/trema#
引用する際は、プライベートのメソッドであるl7_dump()内だけコピーして、packet_inイベントハンドラの中で呼び出せばOKです。
コメント
コメントを投稿する
SpecialPR