【独自プロトコルを分析】nDPI L7アプリケーション分析ライブラリの拡張方法

mieruka.link読者の皆様、おはようございます! 管理人の伊集院です。

本日も夏休み期間中であることを利用して、少しディープな表題のネタをご紹介したいと思います。

前回の記事【L7アプリケーション分析を簡単に実現する方法】nDPIとは?使い方をマスターしよう!!で、nDPIの開発・実行環境を準備しました。独自プロトコル分析、nDPIL7アプリケーション分析拡張にご興味のある方は是非ご一読ください。

今回の記事は、前回の記事の続きで独自プロトコルを解析できるようにnDPIを拡張しようといったお話です。

前回の記事と本記事を読むことで、nDPIでサポートしていないアプリケーションの分析が可能となり、例えば組織で特殊なアプリケーションを使っているよ!なんて方もそのアプリに特化した分析をntopで実現できます。

nDPI拡張手順

nDPIの拡張手順は、以下の手順となります。

  1. src/include/ndpi_protocol_ids.hに、新しいプロトコルのIDを追加する
  2. src/lib/protocols/ に新しいプロトコルのdissectorを配置する ※開発のメーン部分です
  3. 変数を利用する場合は、 src/include/ndpi_typedefs.h in ndpi_flow_tcp_struct (for TCP only), ndpi_flow_udp_struct (for UDP only), or ndpi_flow_struct (for both)に、それぞれ定義する。※今回は利用しません
  4. 新しく、src/include/ndpi_protocols.hにDissector関数を定義する
  5. ビットマスクを選択する(変更の必要なし) src/include/ndpi_define.h
  6. ndpi_set_protocol_detection_bitmask2 in: src/lib/ndpi_main.c に新しいエントリーを追加する
  7. ndpi_init_protocol_defaults in: src/lib/ndpi_main.cにデフォルトポートを追加する
  8. ./autogen.sh
  9. ./configure –enable-debug-messages CFLAG=”-g”
  10. make

独自プロトコルのpcapファイルを準備

今回は、分かりみが良いように以前ご紹介した【オリジナルパケットの作成方法】Wireshark達人への道 第十四歩 独自パケットの作成方法で作成したpcapファイルを解析したいと思います。※data部分を!mierukaに変更しております。

図1 独自プロトコルをWiresharkで表示しているところ

こちらのpcapファイルを解析し、アプリケーション名MierukaでnDPIが解析してくれるように開発していきます。

プロトコルIDの追加

src/include/ndpi_protocol_ids.h にMierukaプロトコルのIDを追記します。

2021年8月12日現在、263までのアプリケーションが登録されていたので264としました。

  NDPI_PROTOCOL_AVAST_SECUREDNS       = 263, /* Toni Uhlig <matzeton@googlemail.com> */
  NDPI_PROTOCOL_MIERUKA               = 264, /* Mieruka.link */

修正はこの一行だけです。

新しいDissectorの登録

nDPI拡張のメーン部分です。

src/lib/protocols/syslog.cを参考にsrc/lib/protocols/mieruka.cを作りました。

図1の独自プロトコル判別に利用する情報は、データーの最初の文字が”!”マークであること。

一文字目が”m”, 7文字目が”a”といったかなり手抜きな実装です。

本記事は開発の流れをご理解いただくことを目的に作成しておりますので、本格的なDissectorにはなっていないことご了承ください。

  1 /*
  2  * mieruka.c
  3  *
  4  * Copyright (C) 2009-11 - ipoque GmbH
  5  * Copyright (C) 2011-21 - ntop.org
  6  *
  7  * This file is part of nDPI, an open source deep packet inspection
  8  * library based on the OpenDPI and PACE technology by ipoque GmbH
  9  *
 10  * nDPI is free software: you can redistribute it and/or modify
 11  * it under the terms of the GNU Lesser General Public License as published by
 12  * the Free Software Foundation, either version 3 of the License, or
 13  * (at your option) any later version.
 14  *
 15  * nDPI is distributed in the hope that it will be useful,
 16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18  * GNU Lesser General Public License for more details.
 19  *
 20  * You should have received a copy of the GNU Lesser General Public License
 21  * along with nDPI.  If not, see <http://www.gnu.org/licenses/>.
 22  *
 23  */
 24
 25 #include "ndpi_protocol_ids.h"
 26
 27 #define NDPI_CURRENT_PROTO NDPI_PROTOCOL_MIERUKA
 28
 29 #include "ndpi_api.h"
 30
 31 static void ndpi_int_mieruka_add_connection(struct ndpi_detection_module_struct
 32                                            *ndpi_struct, struct ndpi_flow_struct *flow)
 33 {
 34   ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_MIERUKA, NDPI_PROTOCOL_UNKNOWN);
 35 }
 36
 37 void ndpi_search_mieruka(struct ndpi_detection_module_struct
 38                         *ndpi_struct, struct ndpi_flow_struct *flow)
 39 {
 40   struct ndpi_packet_struct *packet = &flow->packet;
 41   u_int8_t i;
 42
 43   NDPI_LOG_DBG(ndpi_struct, "search mieruka\n");
 44
 45   if (packet->payload_packet_len == 8 && packet->payload[0] == '!') {
 46     NDPI_LOG_DBG2(ndpi_struct, "checked len == 8 and first symbol=!\n");
 47
 48     if (packet->payload[1] == 'm' && packet->payload[7] == 'a') {
 49      NDPI_LOG_INFO(ndpi_struct, "found mieruka\n");
 50      ndpi_int_mieruka_add_connection(ndpi_struct, flow);
 51     } else {
 52      NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
 53     }
 54   }
 55 }
 56
 57
 58 void init_mieruka_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask)
 59 {
 60   ndpi_set_bitmask_protocol_detection("Mieruka", ndpi_struct, detection_bitmask, *id,
 61                                       NDPI_PROTOCOL_MIERUKA,
 62                                       ndpi_search_mieruka,
 63                                       NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
 64                                       SAVE_DETECTION_BITMASK_AS_UNKNOWN,
 65                                       ADD_TO_DETECTION_BITMASK);
 66
 67   *id += 1;
 68 }

37行目のndpi_search_mieruka()が、Dissectorプログラムの要部分です。

パケットlengthが8バイトで、かつpayloadデータの一文字目が’!’であることを確認しています。

さらに、1文字目、7文字目のチェックが通ればMierukaプロトコルと判断します。

Dissector関数の定義

src/include/ndpi_protocols.h に検索関数を定義します。

58行目の内容をそのまま記載します。

void init_mieruka_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask);

ビットマスクとデフォルトポート定義

src/lib/ndpi_main.cndpi_set_protocol_detection_bitmask2, ndpi_init_protocol_defaults にそれぞれ追記していきます。※例えば、ndpi_set_protocol_detection_bitmask2を省略すると、ndpi_init_protocol_defaultsのみが実行される結果となりますので忘れずに追加してください。

snip

3739   /* MIERUKA */
3740   init_mieruka_dissector(ndpi_str, &a, detection_bitmask);

snip

 953   ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MIERUKA,
 954                           "Mieruka", NDPI_PROTOCOL_CATEGORY_SYSTEM_OS,
 955                           ndpi_build_default_ports(ports_a, 6363, 0, 0, 0, 0) /* TCP */,
 956                           ndpi_build_default_ports(ports_b, 6363, 0, 0, 0, 0) /* UDP */);

後は手順通り、コンパイルするだけです。

本プログラムの実行結果は、以下の通りです。

mieruka@ThinkPad-X250:~/ndpidev/nDPI-dev/example$ ./ndpiReader -v 2 -V 4 -i ../../mieruka_own.pcapng

-----------------------------------------------------------
* NOTE: This is demo app to show *some* nDPI features.
* In this demo we have implemented only some basic features
* just to show you what you can do with the library. Feel
* free to extend it and send us the patches for inclusion
------------------------------------------------------------

Using nDPI (4.1.0) [1 thread(s)]
Using libgcrypt version 1.8.5
Reading packets from pcap file ../../mieruka_own.pcapng...
ndpi_main.c:ndpi_set_bitmask_protocol_detection:3511 - [Unknown]: [NDPI] Internal error: protocol Mining/42 has been already registered
ndpi_main.c:ndpi_set_protocol_detection_bitmask2:4049 - [Unknown]: callback_buffer_size is 170
Running thread 0...
ndpi_main.c:ndpi_detection_process_packet:5412 - [Unknown]: START packet processing
ndpi_main.c:ndpi_init_packet_header:4370 - [Unknown]: ipv4 header
ndpi_main.c:ndpi_detection_get_l4_internal:4214 - [Unknown]: ipv4 header
protocols/mieruka.c:ndpi_search_mieruka:43  - [Mieruka]: search mieruka
protocols/mieruka.c:ndpi_search_mieruka:46  - [Mieruka]: checked len==8 and first symbol=!
payload_packet_len: 8
protocols/mieruka.c:ndpi_search_mieruka:50  - [Mieruka]: found mieruka

nDPI Memory statistics:
        nDPI Memory (once):      221.86 KB
        Flow Memory (per flow):  2.48 KB
        Actual Memory:           1.84 MB
        Peak Memory:             1.84 MB
        Setup Time:              6 msec
        Packet Processing Time:  0 msec

Traffic statistics:
        Ethernet bytes:        74            (includes ethernet CRC/IFC/trailer)
        Discarded bytes:       0
        IP packets:            1             of 1 packets total
        IP bytes:              50            (avg pkt size 50 bytes)
        Unique flows:          1
        TCP Packets:           0
        UDP Packets:           1
        VLAN Packets:          0
        MPLS Packets:          0
        PPPoE Packets:         0
        Fragmented Packets:    0
        Max Packet size:       16
        Packet Len < 64:       1
        Packet Len 64-128:     0
        Packet Len 128-256:    0
        Packet Len 256-1024:   0
        Packet Len 1024-1500:  0
        Packet Len > 1500:     0
        nDPI throughput:       3.52 K pps / 1.99 Mb/sec
        Analysis begin:        06/May/2020 20:56:49
        Analysis end:          06/May/2020 20:56:49
        Traffic throughput:    0.00 pps / 0 b/sec
        Traffic duration:      0.000 sec
        Guessed flow protos:   0
        DPI Packets (UDP):     1             (1.00 pkts/flow)


Detected protocols:
        Mieruka              packets: 1             bytes: 50            flows: 1


Protocol statistics:
        Acceptable                      50 bytes

        1       UDP 192.168.1.8:63721 -> 192.168.1.254:6363 [proto: 264/Mieruka][ClearText][cat: System/18][1 pkts/50 bytes -> 0 pkts/0 bytes][Goodput ratio: 16/0][< 1 sec][Plen Bins: 100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

Debug部分で、作成したDissectorの条件分岐に入っていることが分かります。そして、Detected protocols:でしっかりとMierukaプロトコル判別ができていることを確認できました。

お疲れさまでした。

(Visited 491 times, 1 visits today)
The following two tabs change content below.
【好きなもの】 インフラ技術が好き。古いものが好き。 【生きてきたフィールド】 システム運用、ソフトウェア開発、ミドルウェア検証、OSSサポート、プリセールスエンジニア、プロジェクトマネジメント 【このサイトでの役割】 サイト管理者。