nDPI——快速入门指南(翻译官方文档)

该翻译文档转载自:https://blog.csdn.net/A_lber_t/article/details/89552332,我自己做了一些修改

官方文档(英文版)链接:https://github.com/ntop/nDPI/tree/3.0-stable/doc


目录

1. nDPI介绍

1.1  下载源

2.  nDPI库

2.1  编译nDPI源码

 2.2  编译示例ndpiReader源码

2.3  ndpiReader命令行选项

2.4  协议文件

3.  示例

3.1  实时捕获模式

3.2  pcap 捕获模式

3.3  协议文件

4.  API nDPI

5.  开发nDPI自定义协议

5.1  介绍

5.2  创建新的协议

5.3  添加你的协议到nDPI


1. nDPI介绍

nDPI是一个基于OpenDPI的DPI库(Deep Packet Inspection,深度包检测),目前由ntop维护。

为了给您提供一个跨平台的DPI体验,我们除了支持Unix/Linux外,同时也支持Windows。不仅如此,我们已经通过修改nDPI,使得它更加适合于流量监控应用,我们通过禁用那些对网络流量监控不必要的特性,已经实现了这一功能,因此也加快了DPI引擎的速度。

nDPI允许应用层协议的检测,而不管该协议使用的端口是什么。这意味着不仅可以检测使用非标准端口的知名协议(例如不使用80端口的HTTP协议),而且可以检测使用标准端口传输的其他协议(例如在80端口检测skype流量)。这是由于在目前“端口=应用”的概念不再适用。

在过去的几个月里,我们也新增加了几个功能特性,包括:

  1. 示例ndpiReader应用在速度/功能方面和封装支持上都得到了加强。(例如你现在可以对GTP隧道流量进行分析)
  2. 能够将nDPI编译到Linux内核中,以便于你能使用它开发高效的基于内核的模块。
  3. 多方面速度加强,nDPI现在比他的前身(之前的版本)更快。
  4. 添加了许多协议(到目前为止我们支持大约200个协议),其中包括如SAP与Citrix等的“业务”协议,也有像Dropbox与Spotify的“桌面”协议。
  5. 能够去定义基于端口(和端口范围)的协议检测,以便于你能使用经典的基于端口的检测来去补充协议检测。
  6. 为了能让nDPI支持加密的链接,我们已经为SSL(包括服务器与客户端)证书添加了解码器。因此,我们能够使用加密证书来理解弄清楚协议。同时这也能让我们去识别如Citrix Online与Apple ICloud等一般无法检测到的协议。
  7. 能通过使用基于字符串的匹配来支持子协议。

1.1  下载源

当你在构建ntop与nProbe时nDPI会自动被下载。当然也没有什么能阻止你将其用作一个独立的DPI库。你可以从https://github.com/ntop/nDPI  下载源码。

 

2.  nDPI库

2.1  编译nDPI源码

开始使用nDPI库非常地简单。为了编译这个库,你必须满足一些先决条件比如:

  1. GNU     autotools/libtool
  2. gawk
  3. gcc

为了实现这些,你需要使用以下命令来安装他们:

Fedora         yum groupinstall Development tools
               yum install automake libpcap-devel gcc-c++ libtool

Debian         apt-get install build-essential libpcap-dev

Mac OSX        port install XXX (Please install macports)       

一旦你完成了上面的安装,你就能使用以下命令编译nDPI源码:

cd <nDPI source code directory>
./autogen.sh
./configure
make

 2.2  编译示例ndpiReader源码

开始使用ndpiReader也很简单。为了编译它你必须使用以下命令:

cd <nDPI source code directory>/example 
make

2.3  ndpiReader命令行选项

 这个示例ndpiReader应用在速度/功能分析方面和封装支持上均能被使用。特别的是,ndpiReader能够指定很多命令行选项。

下面列举了可使用的命令选项和每一个选项的简要简要介绍:

 

ndpiReader  -i <file|device> [-f <filter>][-s <duration>]
            [-p <protos>][-l <loops> [-q][-d][-h][-t][-v <level>]
            [-n <threads>] [-w <file>] [-j <file>]


Usage:
-i <file.pcap|device>        Specify a pcap file/playlist to read packets from or a
                             device for live capture (comma-separated list)
                             指定一个pcap文件/播放列表来读取数据包,或者指定一个用于实时捕获的                            
                             设备(逗号分隔的列表)
-f <BPF filter>              Specify a BPF filter for filtering selected traffic
                             指定一个BPF过滤器来过滤选定的流量
-s <duration>                Maximum capture duration in seconds (live traffic capture                             
                             only)
                             最大捕获持续时间(以秒计)(仅实时捕获流量)
-p <file>.protos             Specify a protocol file (eg. protos.txt)
                             指定一个协议文件(例如protos.txt)
-l <num loops>               Number of detection loops (test only)
                             检测循环次数(仅限测试)
-n <num threads>             Number of threads. Default: number of interfaces in -i.
                             Ignored with pcap files.
                             线程的数量,默认是在i命令中接口的数量,不算pcap文件
-j <file.json> |             Specify a file to write the content of packets in .json
format
                             指定一个文件以.json格式写入包的内容
-d                           Disable protocol guess and use only DPI
                             禁用协议猜测并仅使用DPI
-q                           Quiet mode
                             静音模式
-t                           Dissect GTP tunnels
                             解剖GTP隧道
-r                           Print nDPI version and git revision
                             打印nDPI版本和git版本
-w <path>                    Write test output on the specified file. This is useful
                             for testing purposes in order to compare results across runs
                             在指定的文件上写测试输出
-h                           This help
-v <1|2>                     Verbose 'unknown protocol' packet print. 1=verbose,2=very verbose
                             详细的“未知协议”包打印。1 =冗长,2 =非常冗长

-i<file.pcap |device>

       这项命令用于指定一个pcap文件来读取数据包,或者指定一个用于实时捕获的设备。而且只能指定两者当中的一个

-f<BPF filter>

       指定一个BPF过滤器用来过滤选定的流量。它只允许nDPI接受那些和过滤器匹配的数据包(如果被指定的话)。

-s<duration>

       定义了捕获持续时间,以秒为单位,仅用于实时流量捕获。

-p<file.protos>

       指定了一个协议文件(例如protos.txt)来扩展对子协议和基于端口协议检测的支持。尤其需要小心的是,协议一旦被定义到protos文件中就会覆盖之前的已经存在的协议。

-l<num loops>

       检测循环数(仅用与测试)

-d

       这个标志会禁用nDPI协议猜测,仅使用DPI。

-h

       打印ndpiReader帮助

-v<1|2>

       使用这个标志时,ndpiReader会生成详细的输出,这个输出能被用于调试其性能。数字1是显示带有“未知协议”数据包的最低等级,而2级会显示地更加详细,两者只能指定其一。

UDP 62.101.93.101:53 > 192.168.1.132:56130 [proto: 5/DNS][2 pkts/260 bytes][chat.stackoverflow.com]
TCP 192.168.1.132:59323 > 62.161.94.220:80 [proto: 7/HTTP][8 pkts/1925 bytes][]
UDP 62.101.93.101:53 > 192.168.1.132:56682 [proto: 5/DNS][2 pkts/258 bytes][diy.stackexchange.com]
UDP 62.101.93.101:53 > 192.168.1.132:56916 [proto: 5/DNS][2 pkts/524 bytes][conjugator.reverso.net]
.....................................................................................
.....................................................................................
TCP 192.168.1.132:59323 > 62.161.94.220:80 [proto: 7/HTTP][8 pkts/1925 bytes][]
Undetected flows:
TCP 192.168.1.132:57995 > 157.55.133.142:12350 [proto: 0/Unknown][3 pkts/208 bytes][]
TCP 65.55.223.47:33033 > 192.168.1.132:57997 [proto: 0/Unknown][8 pkts/547 bytes][]
TCP 127.23.238.168:16384 > 240.199.103.219:0 [proto: 0/Unknown][11 pkts/1611 bytes][]
TCP 127.23.238.168:0 > 240.199.103.219:16384 [proto: 0/Unknown][11 pkts/2734 bytes][]

2.4  协议文件

       nDPI能够通过基于字符串的匹配支持子协议。这是由于许多新的子协议比如Apple iCloud/iMessage、WhatsApp和许多其他使用HTTP(s)的协议能够通过解码SSL证书主机或者HTTP“Host:”被检测到。因此我们决定将一个基于流行的Aho-Corasick 算法的高效字符匹配库嵌入到nDPI中,用于数十万子字符的高效匹配(即在普通硬件上能足够快地支持10Gb的流量)。

       你可以在运行时通过使用一个用以下格式的协议文件来指定子协议:

# Subprotocols
# Format:
# host:"<value>",host:"<value>",.....@<subproto>
host:"googlesyndacation.com"@Google
host:"venere.com"@Veneer

       除此之外,你也能使用以下格式来指定一个基于端口的检测:

# Format:
# <tcp|udp>:,<tcp|udp>:,.....@
tcp:81,tcp:8181@HTTP
udp:5061-5062@SIP
tcp:860,udp:860,tcp:3260,udp:3260@iSCSI
tcp:3000@ntop

       你可以使用ndpiReader这个应用(使用 –p 选项)来测试你的自定义配置。或者你可以使用ndpi_load_protocls_file() nDPI API调用来增强你自己的应用。

 

3.  示例

在这一节我们会展示一些ndpiReader的使用范例。

3.1  实时捕获模式

       下面这个例子将会展示ndpiReader的实时捕获模式。使用参数-i指定接口设备,参数-s 指定实时捕获持续时间。

$ ./ndpiReader -i eth0 -s 20
-----------------------------------------------------------
* 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 nDPI ($Revision: #### $)
Capturing live traffic from device eth0...
Capturing traffic up to 20 seconds

pcap file contains
    IP packets:     2390     of 2391 packets total
    IP bytes:       1775743
    Unique flows:   78
    nDPI throughout: 122.30 pps / 709.92 Kb/sec
    Guessed flow protocols: 0

Detected protocols:
    DNS             packets: 57         bytes: 7904         flows: 28
    SSL_No_Cert     packets: 483        bytes: 229203       flows: 6
    FaceBook        packets: 136        bytes: 74702        flows: 4
    DropBox         packets: 9          bytes: 668          flows: 3
    Skype           packets: 5          bytes: 339          flows: 3
    Google          packets: 1700       bytes: 619135       flows: 34

3.2  pcap 捕获模式

       创建一个pcap文件最简单的方法就是通过使用tcpdump命令,就像下面这个例子:

ntop$ tcpdump -ni eth0 -s0 -w /var/tmp/capture.pcap -v
tcpdump: listening on en1, link-type EN10MB (Ethernet), capture size 65535 bytes
Got 0
Got 64
Got 75
Got 76
^C122 packets captured
122 packets received by filter
0 packets dropped by kernel

       一旦pcap文件被创建,你就能启动ndpiReader,使用参数-i:

 

$ ./ndpiReader -i /var/tmp/capture.pcap
-----------------------------------------------------------
* 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 nDPI ($Revision: #### $)
Reading packets from pcap file /var/tmp/capture.pcap...

pcap file contains
        IP packets:     4911         of 4911 packets total
        IP bytes:       3321544
        Unique flows:   145
        nDPI throughout: 612.80 K pps / 3.09 Gb/sec
        Guessed flow protocols: 11

Detected protocols:
        Unknown         packets: 6         bytes: 764         flows: 1
        DNS             packets: 50        bytes: 6158        flows: 25
        HTTP            packets: 2537      bytes: 841638      flows: 73
        SSL_No_Cert     packets: 1522      bytes: 303380      flows: 10
        SSL             packets: 24        bytes: 1648        flows: 8
        FaceBook        packets: 644       bytes: 201216      flows: 17
        Skype           packets: 11        bytes: 872         flows: 6

3.3  协议文件

       为了阐明协议文件的特性,我们现在将解释怎样让你识别来自ntop.org的流。

       例如我们可以通过编辑protos.txt文件来实现它:

ntop$ echo 'host:"ntop.org"@nTop'> protos.txt

       一旦这个协议文件已经被修改,你可以启动ndpiReader,使用参数 –p:

$ ./ndpiReader -i en1 -s 30 -p protos.txt
-----------------------------------------------------------
* 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 nDPI ($Revision: #### $)
Capturing live traffic from device en1...
Capturing traffic up to 30 seconds
WARNING: only IPv4/IPv6 packets are supported in this demo (nDPI supports both IPv4
and IPv6), all other packets will be discarded

pcap file contains
        IP packets:     4755     of 4757 packets total
        IP bytes:       1766370
        Unique flows:   245
        Guessed flow protocols: 16

Detected protocols:
        Unknown         packets: 1         bytes: 94         flows: 1
        DNS             packets: 38        bytes: 5160       flows: 19
        HTTP            packets: 265       bytes: 59831      flows: 20
        SSDP            packets: 20        bytes: 9564       flows: 14
        SSL             packets: 33        bytes: 2572       flows: 13
        DropBox         packets: 17        bytes: 2481       flows: 6
        Skype           packets: 12        bytes: 944        flows: 2
        Google          packets: 2544      bytes: 612765     flows: 94
        nTop            packets: 407       bytes: 66765      flows: 32

4.  API nDPI

       在这一节中nDPI API是重点。

       示例ndpiReader现在有一个基础的例子用来展示如何初始化这个库。需要一个已经编译好的库和一个合适配置的Makefile(即示例Makefile)。

       想要在你的应用中开始使用nDPI的API,除了你自己的包含外,必须也添加下面这个包含文件:

#include"dpi_main.h"

       这个库可以像下面这样初始化:

1、声明协议位掩码,初始化检测模块:

NDPI_PROTOCOL_BITMASK all;
ndpi_struct = ndpi_init_detection_module(
        detection_ticks_resolution,
        malloc_wrapper,
        free_wrapper,
        debug_printf);

这个函数允许你初始化检测模块。字段有如下含义:

  • U_int32_t ticks_per_second

每秒时间戳分辨率(比如1000每毫秒分辨率)。

  • void*(*_ndpi_malloc)(unsigned long size);

指向一个内存分配器的函数指针。

  • void*(*_ndpi_free)(void*prt);

指向一个调试输出函数的函数指针,在生产环境下置空(NULL)

2、通过适当的宏启用所有协议(注意,如果需要,可以启用协议的一个子集),并在检测模块中设置它们

// enable all protocols
NDPI_BITMASK_SET_ALL(all);
ndpi_set_protocol_detection_bitmask2(ndpi_struct, &all);

这个函数能让你设置已经定义到检测模块中的协议位掩码。

3、为了加载一个存在的协议文件,你必须使用如下函数:

dpi_load_protocols_file(ndpi_struct, _protoFilePath);

4、每当从你的pcap文件或者入口设备中捕获到流时,它们可以通过使用以下函数分析:

protocol = (const u_int32_t)ndpi_detection_process_packet(
        ndpi_struct,
        ndpi_flow,iph ? (uint8_t *)iph : (uint8_t *)if,
        ipsize,
        time,
        src,
        dst);

 

这些字段有以下的含义:

  • struct ndpi_detection_module_struct*ndpi_struct;

检测模块。

  • struct ndpi_flow_struct*flow;

指向连接状态机的流空指针。

  • const unsigned char*packet;

这个packet作为一个无符号的字符指针,长度为packetlen。这个指针必须指向第三层(IP报头)。

  • const unsigned short packetlen;

packetlen包的长度。

  • const U_int32_t current_tickt;

数据包的当前时间戳。

  • struct ndpi_id_struct*src;

指向源订阅状态机的空指针。

  • struct ndpi_id_struct*dst;

指向目的订阅状态机的空指针。

5、一旦流被分析后,有必要通过下面的函数来摧毁检测模块。

 ndpi_exit_detection_module(ndpi_struct, free_wrapper);

这些字段有以下含义:

  • struct ndpi_detection_module_struct*ndpi_struct;

需要被消除的检测模块。

  • void*(*_ndpi_free)(void*prt);

指向一个内存释放函数的函数指针。

 

  如需进一步的信息,我们建议可以阅读以下文件:

nDPI/example/ndpiReader.c,

nDPI/src/include/ndpi_structs.h,

nDPI/src/include/ndpi_public_functions.h

nDPI/src/ndpi_main.c.

协议解析器文件被包含在nDPI/src/protocols 目录下

 

5.  开发nDPI自定义协议

在这一节中,我们将展示将你的协议包含在nDPI中的方法。

5.1  介绍

       每个nDPI协议都会作为一个入口函数被实现,在运行时通过nDPI被使用。nDPI有几个协议可以被用来当作这个方面的例子。下面,我们列出了一些主要的概念,如果你打算开发一个nDPI协议,这些是你必须知道的。

5.2  创建新的协议

       每一个协议都必须在下面的头文件中有一个对应的#define:

<nDPI source code directory>/src/include/ndpi_protocols_osdpi.h

       例如:

#define NDPI_PROTOCOL_MY_PROTOCOL     171

NDPI_PROTOCOL_MY_PROTOCOL是这个协议的名字,171是这个协议的ID,且必须是独一无二的。

       协议被定义好了之后,你必须创建一个协议源文件,就像:

<nDPI source code directory>/src/lib/protocols/my_protocol.c

包括以下内容:

#include "ndpi_utils.h"
#ifdef NDPI_PROTOCOL_MY_PROTOCOLS
.....
#endif

在里面,需要定义一个入口函数,如:

void ndpi_search_my_protocol(
struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow)
{
    struct ndpi_packet_struct *packet = &flow->packet;

    NDPI_LOG(NDPI_PROTOCOL_MY_PROTOCOL, ndpi_struct, NDPI_LOG_DEBUG, "my protocol detection...\n");

    /* skip marked packets by checking if the detection protocol stack */

    if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_MY_PROTOCOL) {
        ndpi_check_my_protocol(ndpi_struct, flow);
    }
}

 

以及一个检测核心函数,用来处理一个流的数据包,包括以下内容:

static void ndpi_check_my_protocol(
struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow)
{
        struct ndpi_packet_struct *packet = &flow->packet;
        u_int32_t payload_len = packet->payload_packet_len;
        .....
        .....
        if(“Found Protocol”) {
            NDPI_LOG(NDPI_PROTOCOL_MY_PROTOCOL, ndpi_struct,
            NDPI_LOG_DEBUG, "Found my protocol.\n");
            ndpi_int_my_protocol_add_connection(ndpi_struct, flow);
            return;
        }
        /*Exclude Protocol*/
        NDPI_LOG(NDPI_PROTOCOL_MY_PROTOCOL, ndpi_struct, NDPI_LOG_DEBUG,“exclude my protocol.\n");
        NDPI_ADD_PROTOCOL_TO_BITMASK(
                flow->excluded_protocol_bitmask,
                NDPI_PROTOCOL_MY_PROTOCOL);
        }
}

以及一个特定的函数用来报告关于协议正确的识别信息,如:

static void ndpi_int_my_protocol_add_connection(
            struct ndpi_detection_module_struct *ndpi_struct,
            struct ndpi_flow_struct *flow,
            u_int8_t due_to_correlation)
{
    ndpi_int_add_connection(ndpi_struct, flow,
                NDPI_PROTOCOL_MY_PROTOCOL,
                /*Choose the type of your protocol*/
                NDPI_CORRELATED_PROTOCOL or NDPI_REAL_PROTOCOL);
}    

5.3  添加你的协议到nDPI

       协议被创建之后,你必须在下面的头文件中声明你的入口函数:

<nDPI source code directory>/src/include/ndpi_protocols.h

包括如下内容:

/* my protocol entry */
void ndpi_search_my_protocol(
        struct ndpi_detection_module_struct *ndpi_struct,
        struct ndpi_flow_struct *flow);

每个协议必须与一个NDPI_SELECTION_BITMASK相关联。NDPI_SELECTION_BITMASK的完整列表被包含在文件:

<nDPI source code directory>/src/include/ndpi_define.h

在为你的协议选择了一个确定的位掩码之后,你必须通知nDPI新协议的存在,通过编辑文件:

<nDPI source code directory>/src/lib/ndpi_main.c

你需要将你的协议添加到如下函数中:

void ndpi_set_protocol_detection_bitmask2(
            struct ndpi_detection_module_struct *ndpi_struct,
            const NDPI_PROTOCOL_BITMASK * dbm)
.....
.....
.....
#ifdef NDPI_PROTOCOL_MY_PROTOCOL
ndpi_set_bitmask_protocol_detection(ndpi_struct,detection_bitmask,a,
                                    NDPI_PROTOCOL_MY_PROTOCOL,
                                    ndpi_search_my_protocol,
                                    NDPI_SELECTION_BITMASK_MY_PROTOCOL,
                                    SAVE_DETECTION_BITMASK_AS_UNKNOW,
                                    ADD_TO_DETECTION_BITMASK);
/* Update callback_buffer index */
a++;
#endif
.....
.....
.....
ndpi_struct->callback_buffer_size = a;
NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG,
        "callback_buffer_size is %u\n", ndpi_struct-
        >callback_buffer_size);

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值