高速通信計算研究所

slankdevの報告

Cuishark version 2.0開発の雑記

cuishark内部でのパケット解析をlibwiresharkを用いて行うことで, wiresharkの対応プロトコルを全てcuisharkでいじれるようにするという素晴らしい話のための雑記.

開発方針

version1は以下のようになっていた.

version2では以下のようにしようと思う.

そのようにした理由を論す. バックエンドに関しては単純に「wiresharkのdissectorを持ってきたい. 」という単純な理由である. しかしlibwireshark はドキュメントがなかったり少しめんどくさいので苦労すると思われる.

フロントエンドに関しては「TUI書くのクソだるい」という理由である. さすがにcuisharkのフロントエンドをCでゴリゴリ書くよりは書きやすい言語でやりたいなということ.

グルー部分に関しては, バックエンドを「libwiresharkpy」見たいな形にしてctypesでpythonラップしてフロントから叩こうかなと思っている. 今時, linuxのネットワークインターフェースとpcap/pcapngからパケットが読めれば満足なはず(DPDKでもtapリダイレクトは簡単)なので. パケット入力はその二種類でやろうかなと思っている.

Cuishark ver2 設計

以下のコンポーネントを考えている

  • libws_cpp libwiresharkのC/C++ラッパー
  • libws_py libwc_cppをctypesでpythonラップ
  • curasesフロントエンド. これは何も考えてない

libws_cpp

以下tsharkを参考にしている.

  • dissector_new/freeは一回しか行わない
  • dissectorは1パケットごとにresetする
  • 以下の機能を自由に使えることを確認する
    • pcapファイルから受信
    • netifから受信
    • dfilterが使える
    • packet summaryが表示できる
    • packet detail が表示できる (ツリー構造)

libws_py

pythonから以下のことができればOKと思っている.

  • パケットフィルタ(display filter)を叩ける
  • 入力IFを選べる (pcap/pcapng/netif)
  • パケットの生dataが取れる
  • パケットの dissect結果がツリーレベルで取れる.

これらのことを可能にするC/C++プログラムをまずかいて, それをpythonでラップすることにしている.

余談: libwiresharkのいじり方

 

libwiresharkとは

libwiresharkとは, wiresharkの中で利用されている. パケット解析のライブラリである. wiresharkは莫大な量のプロトコルに対応しているが, それらのプロトコルの解析部分 (wireshark内部ではdissectorと呼ぶ) はlibwiresharkのサブセットとして, wiresharkとは独立している. libwiresharkはwiresharkの開発者があとから実装の一部を分離しただけの「ドキュメントもほとんどない. 使用方法が謎なライブラリである.」

しかし, これを使いこなすことができれば, 事実上ではwiresharkの対応している豊富なプロトコルが簡単に解析できるプログラムがかけるはずである. (そのようなソフトウェアはとても少ない.)

もっともシンプルなコード

write soon

typedef struct _packet_info {
  const char *current_proto;        /**< name of protocol currently being dissected */
  struct epan_column_info *cinfo;   /**< Column formatting information */
  guint32 presence_flags;           /**< Presence flags for some items */
  guint32 num;                      /**< Frame number */
  nstime_t abs_ts;                  /**< Packet absolute time stamp */
  nstime_t rel_ts;                  /**< Relative timestamp (yes, it can be negative) */
  frame_data *fd;
  union wtap_pseudo_header *pseudo_header;
  wtap_rec *rec;                    /**< Record metadata */
  GSList *data_src;                 /**< Frame data sources */
  address dl_src;                   /**< link-layer source address */
  address dl_dst;                   /**< link-layer destination address */
  address net_src;                  /**< network-layer source address */
  address net_dst;                  /**< network-layer destination address */
  address src;                      /**< source address (net if present, DL otherwise )*/
  address dst;                      /**< destination address (net if present, DL otherwise )*/
  guint32 vlan_id;                  /**< First encountered VLAN Id if present otherwise 0 */
  const char *noreassembly_reason;  /**< reason why reassembly wasn't done, if any */
  gboolean fragmented;              /**< TRUE if the protocol is only a fragment */
  struct {
    guint32 in_error_pkt:1;         /**< TRUE if we're inside an {ICMP,CLNP,...} error packet */
    guint32 in_gre_pkt:1;           /**< TRUE if we're encapsulated inside a GRE packet */
    guint32 in_erspan_i:1;          /**< TRUE if we're encapsulated inside an ERSPAN type I packet */
  } flags;
  port_type ptype;                  /**< type of the following two port numbers */
  guint32 srcport;                  /**< source port */
  guint32 destport;                 /**< destination port */
  guint32 match_uint;               /**< matched uint for calling subdissector from table */
  const char *match_string;         /**< matched string for calling subdissector from table */
  gboolean use_endpoint;            /**< TRUE if endpoint member should be used for conversations */
  struct endpoint* conv_endpoint;   /**< Data that can be used for conversations */
  guint16 can_desegment;
  guint16 saved_can_desegment;
  int desegment_offset;             /**< offset to stuff needing desegmentation */
#define DESEGMENT_ONE_MORE_SEGMENT 0x0fffffff
#define DESEGMENT_UNTIL_FIN        0x0ffffffe
  guint32 desegment_len;
  guint16 want_pdu_tracking;
  guint32 bytes_until_next_pdu;
  int     p2p_dir;
  GHashTable *private_table;    /**< a hash table passed from one dissector to another */

  wmem_list_t *layers;      /**< layers of each protocol */
  guint8 curr_layer_num;       /**< The current "depth" or layer number in the current frame */
  guint16 link_number;

  guint16 clnp_srcref;          /**< clnp/cotp source reference (can't use srcport, this would confuse tpkt) */
  guint16 clnp_dstref;          /**< clnp/cotp destination reference (can't use dstport, this would confuse tpkt) */

  int link_dir;                 /**< 3GPP messages are sometime different UP link(UL) or Downlink(DL) */

  GSList* proto_data;          /**< Per packet proto data */

  GSList* dependent_frames;     /**< A list of frames which this one depends on */

  GSList* frame_end_routines;

  wmem_allocator_t *pool;      /**< Memory pool scoped to the pinfo struct */
  struct epan_session *epan;
  const gchar *heur_list_name;    /**< name of heur list if this packet is being heuristically dissected */
} packet_info;

struct epan_dissect {
        struct epan_session *session;
        tvbuff_t        *tvb;
        proto_tree      *tree;
        packet_info     pi;
};
typedef struct epan_dissect epan_dissect_t;

struct data_source {
        tvbuff_t *tvb;
        char *name;
};

References

某メモ

この記事はメモであり, 編集中の内容です.

こんなことがありまして...

  • パケット解析プログラム開発
  • DPDKの基礎,入門
  • 簡単なパケットフィルタ開発
  • 10GbEの高性能化

いただいたご意見

  • XDP,Netmapとの比較
  • IP/TCP/UDP/SSL/QUICなど使いたい時のスタックどう用意するか
  • IP/UDPは自作方法紹介
  • OSSなど活用方法
  • Encap/Decapとか

NFVガイドラインのようなものを少しまとめた

以下に置いた(画像部分をhatebuに変換するのが大変だったのでリンクにした) もしリンクがきれていたら, Twitter: @slankdevまで連絡をください. すぐ直します。

github.com

「次世代の通信インフラストラクチャーに対応する効率的な仮想ネットワーク機能(VNF)アーキテクチャー」を読んだのでようやく

  • NFV Whitepaper by Intel HPE
  • Hiroki SHIROKURA @slankdev
  • 2018.07.30

本レポートは以下のLINKのWhitepaperをよんで筆者なりにまとめたものである LINK

続きを読む

DPDKアプリをビルドする自前Makefile

DPDKどドキュメントによると、DPDKを使用したアプリケーションでは用意された雛形のMakefileを 一部変更することでビルド環境を提供しているが、自分で何かをつくりたいときにそんなことを やってられない。

ここでは自分で作成したMakefileでDPDKのアプリケーションをビルドする方法をまとめていく。

答えを見つけるまでのアプローチ方法

以下のアプローチで進めていけば一応絶対わかる。

  • オリジナルのビルド手順をすべて確認する
  • makeにnオプションを与えて実行されるコマンドを確認する
  • そのコマンドから少しずついらないオプションを減らしていく
  • どんなDPDKアプリでもビルドできる状態で限界まで減らす
  • 完成
続きを読む

BSDのNW処理部分の設計実装

自分用雑記. まだ書きかけです.

FreeBSDの黄色い本を読んで自分なりに要約, またSTCPの設計実装のためのメモ ここで出てくる典型的例とはBSDカーネル内での実装のことである.

ソースは以下から入手した - ftp://ftp.freebsd.org/pub/FreeBSD/releases/

続きを読む