ネットワークエンジニアから着物屋さんとして独立しました。ネットショップのIT面を中心にお伝えします

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です。

Comment(0)

コメント

コメントを投稿する