Upgrade to Pro — share decks privately, control downloads, hide ads and more …

pakeana27

Masaya YAMAMOTO
April 27, 2015
800

 pakeana27

パケットモニタリングツール自作のススメ

Masaya YAMAMOTO

April 27, 2015
Tweet

Transcript

  1. ⾃自⼰己紹介 ・⼭山本  雅也(@pandax381)     ・https://github.com/pandax381   ・KLab株式会社(2012/05  〜~)  

      ・「Kラボラトリー」という研究開発部⾨門に所属     ・⽇日々、パケットと戯れたり変なツール作ったり     ・ゲーム開発とは関係ないことばかりやっています   ・書籍     ・Xen3.0による仮想化サーバの構築(絶版)     ・プロトコルスタック⾃自作本(執筆中)
  2. tcpdump  を使うとき ・障害発⽣生時に通信レイヤで異異常がないか確認する     ・サーバに接続できない     ・通信が切切断される  

      ・想定外のタイムアウトが発⽣生する     ・etc..   ・だいたい緊急なのでのんびりWiresharkで解析する暇なし     ・ほとんどの通信は正常なパケットが⾶飛び交う     ・膨⼤大なパケットの中から怪しいパケットを探し出す     ・五感を研ぎ澄ませてパケットの流流れを追う
  3. miruo  #1 ・https://github.com/KLab/miruo   ・Pretty  print  TCP  session  monitor/analizer  

    ・出⼒力力が⾒見見易易い  tcpdump  ⾵風のツール   ・興味がありそうなパケットを抽出して表⽰示
  4. miruo  #3 ・出⼒力力トリガを細かく指定できます     ・確⽴立立から指定時間が経過したセッション       ※

     出⼒力力はセッション終了了時にまとめて⾏行行われるため           接続しっぱなしのセッションには不不向きです     ・再送パケット(SYNの再送は別途指定可能)     ・RSTの受信     ・ACK受信までに時間がかかったパケット     ・etc..
  5. 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の内容も出⼒力力できます
  6. パケットモニタリングツールの作り⽅方  #1 libpcap     ・https://github.com/the-‐‑‒tcpdump-‐‑‒group/libpcap     ・パケットキャプチャの定番ライブラリ  

      ・tcpdump  をライブラリ化したもの     ・tcpdump  と同じフィルタ構⽂文が使える     ・プラットフォームに依存しない  API  を提供してくれる
  7. パケットモニタリングツールの作り⽅方  #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ハンドルを作成   ! ! //  フィルタ構⽂文をコンパイル   //  コンパイル済みのフィルタをハンドルに適⽤用   ! ! //  コールバック関数を登録してキャプチャ開始
  8. パケットモニタリングツールの作り⽅方  #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)  */
  9. パケットモニタリングツールの作り⽅方  #4 ・IPパケットの処理理はとても簡単     ・基本はヘッダを解析するだけ     ・フラグメント化したIPパケットの再構成くらい  

    ・TCPになるとセッションのステート管理理が⼤大変     ・とにかくRFC読んで頑張る     ・libpcap  が取りこぼす可能性もあるので空気読んであげる   ・L7の解析に⼿手を出すとかなり地獄     ・TCPセグメントをまたぐデータどうするの...     ・TCPのストリームを復復元するところからはじめる     ・プロトコルスタックの気持ちを理理解する
  10. gopacket  #1 ・https://github.com/google/gopacket   ・golang  のパケットライブラリ(Google謹製)   ・キャプチャ部分は  libpcap  を

     wrap  している   ・gopacket/tcpassembly  がスゴい!     ・TCP  Assembly  /  Reassembly     ・受信したTCPセグメントを  Reassembly  に⾷食わせると         TCPセッションをリアセンブルできる     ・ファイルを読み出す感覚でストリーム処理理できる
  11. 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