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

pakeana27

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Masaya YAMAMOTO Masaya YAMAMOTO
April 27, 2015
850

 pakeana27

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

Avatar for Masaya YAMAMOTO

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