Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up
for free
pakeana27
Masaya YAMAMOTO
April 27, 2015
2
700
pakeana27
パケットモニタリングツール自作のススメ
Masaya YAMAMOTO
April 27, 2015
Tweet
Share
Featured
See All Featured
jonyablonski
14
1.1k
bryan
30
3.3k
eileencodes
113
25k
3n
163
22k
mza
80
4.1k
aarron
257
36k
revolveconf
200
9.6k
zenorocha
296
40k
reverentgeek
27
1.9k
nonsquared
81
3.3k
carmenhchung
26
1.4k
moore
125
21k
Transcript
パケットモニタリングツール ⾃自作のススメ KLab Inc. @pandax381 第27回 ネットワークパケットを読む会(仮)
#pakeana
⾃自⼰己紹介 ・⼭山本 雅也(@pandax381) ・https://github.com/pandax381 ・KLab株式会社(2012/05 〜~)
・「Kラボラトリー」という研究開発部⾨門に所属 ・⽇日々、パケットと戯れたり変なツール作ったり ・ゲーム開発とは関係ないことばかりやっています ・書籍 ・Xen3.0による仮想化サーバの構築(絶版) ・プロトコルスタック⾃自作本(執筆中)
アジェンダ ・miruo の紹介 ・パケットモニタリングツールの作り⽅方 ・gopacket の紹介
みなさん、今⽇日も⼀一⽇日 tcpdump お疲れさまでした
ところで、どんな時に tcpdump 使いますか?
⼤大好きなあの娘のパケットを(ry
tcpdump を使うとき ・障害発⽣生時に通信レイヤで異異常がないか確認する ・サーバに接続できない ・通信が切切断される
・想定外のタイムアウトが発⽣生する ・etc.. ・だいたい緊急なのでのんびりWiresharkで解析する暇なし ・ほとんどの通信は正常なパケットが⾶飛び交う ・膨⼤大なパケットの中から怪しいパケットを探し出す ・五感を研ぎ澄ませてパケットの流流れを追う
miruo
miruo #1 ・https://github.com/KLab/miruo ・Pretty print TCP session monitor/analizer
・出⼒力力が⾒見見易易い tcpdump ⾵風のツール ・興味がありそうなパケットを抽出して表⽰示
miruo #2 ・2011年年頃に開発したツールですが、現役で活躍してます http://dsas.blog.klab.org/archives/51977201.html ・最近(先週)BSD対応したので Mac でも使えます
miruo #3 ・出⼒力力トリガを細かく指定できます ・確⽴立立から指定時間が経過したセッション ※
出⼒力力はセッション終了了時にまとめて⾏行行われるため 接続しっぱなしのセッションには不不向きです ・再送パケット(SYNの再送は別途指定可能) ・RSTの受信 ・ACK受信までに時間がかかったパケット ・etc..
miruo #4 $ ./miruo --all -i en0 -m http tcp
port 80 listening on en0, link-type EN10MB (Ethernet), capture size 1522 bytes 0001 0.048 | 10.0.0.100:62511 == 125.6.190.6:80 | Total 21 segments, 13397 bytes 0001:0000 17:27:30.093 | SYN_SENT >----S-> SYN_RECV | 1B5B2031/00000000 78 - <mss=1460, 0001:0001 17:27:30.099 | ESTABLISHED <-A--S-< SYN_RECV | 5F9DC421/1B5B2032 78 - <mss=1460, 0001:0002 17:27:30.099 | ESTABLISHED >-A----> ESTABLISHED | 1B5B2032/5F9DC422 66 - <timestamp 0001:0003 17:27:30.099 | ESTABLISHED >-AP---> ESTABLISHED | 1B5B2032/5F9DC422 572 - <timestamp DPI:HTTP:RequestLine >>>> GET /archives/51977201.html HTTP/1.1 DPI:HTTP:Header >>>>>>>>> Host: dsas.blog.klab.org 0001:0004 17:27:30.125 | ESTABLISHED <-AP---< ESTABLISHED | 5F9DC422/1B5B222C 1514 - <timestamp DPI:HTTP:ResponseLine >>> HTTP/1.1 200 OK 0001:**** | | 0001:0016 17:27:30.136 | ESTABLISHED <-A---F< FIN_WAIT1 | 5F9DF149/1B5B222C 66 - <timestamp 0001:0017 17:27:30.136 | CLOSE_WAIT >-A----> FIN_WAIT2 | 1B5B222C/5F9DF149 66 - <timestamp 0001:**** | | 0001:0019 17:27:30.136 | LAST_ACK >-A---F> FIN_WAIT2 | 1B5B222C/5F9DF14A 66 - <timestamp 0001:0020 17:27:30.142 | CLOSED <-A----< TIME_WAIT | 5F9DF14A/1B5B222D 66 - <timestamp ・DPIモードを有効にするとHTTPの内容も出⼒力力できます
パケットモニタリングツールの作り⽅方
パケットモニタリングツールの作り⽅方 #1 libpcap ・https://github.com/the-‐‑‒tcpdump-‐‑‒group/libpcap ・パケットキャプチャの定番ライブラリ
・tcpdump をライブラリ化したもの ・tcpdump と同じフィルタ構⽂文が使える ・プラットフォームに依存しない API を提供してくれる
パケットモニタリングツールの作り⽅方 #2 #include <pcap.h> ! char errmsg[PCAP_̲ERRBUF_̲SIZE] const
char expression[] = “tcp”; struct bpf_̲program bpf; ! pcap = pcap_̲create(“en0”, errmsg); pcap_̲set_̲promisc(pcap, 1); pcap_̲activate(pcap); pcap_̲compile(pcap, &bpf, expression, 0, 0); pcap_̲setfilter(pcap, &bpf); pcap_̲freecode(&bpf); ! pcap_̲loop(pcap, -‐‑‒1, callback, NULL); ! pcap_̲close(pcap); ! ! ! // フィルタ構⽂文 ! ! // 新しいpcapハンドルを作成 ! ! // フィルタ構⽂文をコンパイル // コンパイル済みのフィルタをハンドルに適⽤用 ! ! // コールバック関数を登録してキャプチャ開始
パケットモニタリングツールの作り⽅方 #3 // arg //
pcap_̲loop() の第4引数に渡したユーザーデータ // pkthdr // キャプチャしたパケットに関する時刻やサイズなどの情報 // pktdata // キャプチャしたパケットデータ(イーサネットフレームの先頭を指すポインタ) void callback (u_̲char *arg, const struct pcap_̲pkthdr *pkthdr, const u_̲char *pktdata) { // 受信したパケット(pktdata)を解析してゴニョゴニョする // そのまま出⼒力力すれば 劣劣化版 tcpdump の出来上がり } ! struct pcap_̲pkthdr { struct timeval ts; bpf_̲u_̲int32 caplen; bpf_̲u_̲int32 len; }; /* time stamp */ /* length of portion present */ /* length this packet (off wire) */
パケットモニタリングツールの作り⽅方 #4 ・IPパケットの処理理はとても簡単 ・基本はヘッダを解析するだけ ・フラグメント化したIPパケットの再構成くらい
・TCPになるとセッションのステート管理理が⼤大変 ・とにかくRFC読んで頑張る ・libpcap が取りこぼす可能性もあるので空気読んであげる ・L7の解析に⼿手を出すとかなり地獄 ・TCPセグメントをまたぐデータどうするの... ・TCPのストリームを復復元するところからはじめる ・プロトコルスタックの気持ちを理理解する
gopacket
gopacket #1 ・https://github.com/google/gopacket ・golang のパケットライブラリ(Google謹製) ・キャプチャ部分は libpcap を
wrap している ・gopacket/tcpassembly がスゴい! ・TCP Assembly / Reassembly ・受信したTCPセグメントを Reassembly に⾷食わせると TCPセッションをリアセンブルできる ・ファイルを読み出す感覚でストリーム処理理できる
gopacket #2
gopacket #3 $ ./httpassembly -‐‑‒i en0 2015/04/27 16:15:09 Starting
capture on interface "en0" 2015/04/27 16:15:09 reading in packets 2015/04/27 16:15:23 Received request from stream 10.0.0.100-‐‑‒ >133.242.5.116 61747-‐‑‒>80 : &{GET / HTTP/1.1 1 1 map[Accept: [*/*] User-‐‑‒Agent:[curl/7.30.0]] 0x45e3410 0 [] false www.klab.com map[] map[] <nil> map[] / <nil>} with 0 bytes in request body ... https://github.com/google/gopacket/tree/master/ examples/httpassembly
ありがとうございました