トップページへ



Tremaで書いてみました → L7データのダンプを取る
やはりL7エンジニアとしてはこれが最初のステップかなと。

■■■ 構成図 ■■■
------------------------------
Ubuntu Client
(curlがHTTPクライアント)
eth1 192.168.1.141
|
|
eth1 192.168.1.136
Ubuntu Server
(ApacheがHTTPサーバ)
(OpenFlow コントロールパスとデータパスが両方動作中)
------------------------------


■■■ 動かしてみた結果 ■■■

Ubuntu Client
=======================================
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
================================================================================
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変換してデータを表示させています。


■■■ 設定・ソース ■■■
----------------------------------------------------------------
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#
----------------------------------------------------------------

このスクリプトを引用したい方は、プライベートの関数(rubyでは何て呼ぶんでしょうね?)
であるl7_dump()だけコピペすればOKです。で、packet_inイベントハンドラの中で呼び出す
と。
ソースはこちらからダウンロード. l7_dump.rb.source.txt


■■■ 次にやりたいこと ■■■
今度はこれを踏まえでMan In The Middleの中間に入って書き換えを行う系がいいなと。
SSLやHTTPに限らず普遍的に、「*バイト目~*バイト目までを***の文字列に書き換えた上
でチェックサムも修正して出力」とか。
目的は攻撃ではなくバグ再現の検証です。


質問・間違い指摘などは shimizu@tokyovalley.com へ。
Hiro