ndpi 流量协议分析
1. 介绍
nDPI是一个从OpenDPI发展而来的DPI库,现在由ntop组织负责维护。
为了给你提供一个跨平台DPI的体验,nDPI除了支持Unix平台,还支持Windows(和Mac)。为了使nDPI更加适合应用于流量监控,我们将会持续进行优化,比如一旦发现存在对网络流量监控非必须的、却拖慢了DPI引擎的功能时,可以执行关闭。
不管使用了哪个端口,nDPI都可以探测到实际的应用层协议。这意味着既可以探测运行在非标准端口上的协议(e.g探测运行在非80端口上的http流量),又可以探测运行在一个标准端口上的其他协议(e.g探测运行在80端口上的Skype流量)。这是因为现在端口跟协议关联的概念已经被打破。
在过去的几个月里,我们已经为nDPI增加了以下多个功能:
一个名为ndpiReader的增强型demo
可以被编译进kernel成为一个模块,使其更加高效
从各方面提升了识别速度,目前nDPI在这方面已经远远超过了前代的OpenDPI
新增了大量的协议支持(目前为止已经支持超过180种协议),覆盖范围从商业类协议(如SAP和Citrix)到桌面协议(如Dropbox和Spotify)
可以定义基于端口(端口范围)的协议探测,丰富了传统的仅仅基于端口的探测手段
为了使nDPI支持探测加密连接,我们增加一个用于SSL的解码器(同时支持客户端和服务端),用以找出那些使用了加密证书的协议。这使我们可以识别那些以前无法探测到的协议,比如Citrix和AppleiCloud等
通过基于额外的一些字符串匹配方式,我们可以支持识别一些常见的应用子协议
2. 代码下载
在你搭建ntop和nProbe的过程中nDPI就会自动被下载。也可以作为一个独立的DPI库来使用,源代码可以通过gitclone https://github.com/ntop/nDPI.git下载。
或者:https://github.com/ntop/nDPI/archive/2.4.tar.gz
3. nDPI库安装
安装方式跟平台以及发行版相关,这里列举了一些:
Ubuntu/Debian #apt-get install build-essential
#apt-get install git autoconf automake autogen libpcap-dev libtool
Fedora/CentOS #yum groupinstall "Development tools"
#yum install git autoconf automake autogen libpcap-devel libtool
MacOSX(using http://brew.sh) # brew install autoconf automake libtool git
FreeBSD #pkg install autoconf automake libtool gmake git
依赖环境:
libpcap
autotools
libtool
gawk
gcc
build-essential
安装:
cd nDPI
./autogen.sh
./configure
make
cd example
./ndpiReader --help
Version2.0版本在工程目录下执行make时,默认就编译了example目录下的ndpiReader
4. ndpiReader的命令行选项
以下列出了该demo程序的有效选项以及对应的简单解释
$./ndpiReader -h
ndpiReader-i <file|device> [-f <filter>][-s <duration>][-m<duration>]
[-p<protos>][-l <loops> [-q][-d][-h][-t][-v <level>]
[-n<threads>] [-w <file>] [-j <file>]
Usage:
-i<file.pcap|device> |指定一个需要被识别的pcap文件/文件列表,或者需要被嗅探的
|设备接口/接口列表(文件列表或接口列表使用","作为分隔符)
-f<BPF filter> |指定一条BPF规则的过滤字串
-s<duration> |最大的嗅探时间(显然只在嗅探接口时生效)
-m<duration> | pcap文件分段解析超时时间(显然只在解析pcap文件时生效)
-p<file>.protos |指定一个自定义的协议识别配置文件(eg.protos.txt)
-l<num loops> |指定循环执行嗅探的次数(仅用于测试)
-n<num threads> |指定线程数量,缺省跟设备接口数量对应
|如果传入的是pcap文件时固定使用单线程
-j<file.json> |指定一个输出包内容的json文件
-g<id:id...> |指定线程-CPU亲和关系映射表
-d |禁止协议猜测功能
-q |安静模式,意味着不打印信息
-t |解析GTP隧道协议
-r |打印 nDPI版本和git版本
-w<path> |指定测试信息的输出文件
-h | help信息
-v<1|2|3> |按级别进一步打印包的详细信息,分为1、2、3级
5. 协议文件
通过基于字符串的匹配方式,nDPI可以支持识别应用层的子协议。这是因为存在很多像AppleiCloud/iMessage,WhatsApp等新出现的子协议,以及其他使用http(s)的协议,这些协议可以通过解码主机SSL证书或http头中的"Host"字段而被识别。因此我们决定嵌入一个有效字符串匹配库到nDPI中,这个库基于AC自动机算法来匹配成百上千的有效子串(i.e运行在商业硬件上的nDPI可以处理超过10Gbit的流量)
通过使用一个协议文件,你可以在运行时设置自定义的子协议,这个协议文件的格式如下:
# Subprotocols
# Format:
# host:"<value>",host:"<value>",aaa@qq.com<subproto>
host:"googlesyndication.com"@Google
host:"venere.com"@Venere
host:"kataweb.it",host:"repubblica.it"@Repubblica
host:"ntop"@ntop
你还可以配置基于IP的子协议,格式如下:
# IP based Subprotocols
# Format:
# ip:<value>,ip:<value>,aaa@qq.com<subproto>
ip:aaa@qq.com
你还可以配置基于端口的子协议,格式如下:
# Format:
# <tcp|udp>:<port>,<tcp|udp>:<port>,aaa@qq.com<proto>
tcp:81,tcp:aaa@qq.com
udp:aaa@qq.com
tcp:860,udp:860,tcp:3260,udp:aaa@qq.com
tcp:aaa@qq.com
只需要在运行ndpiReader时加上使用“-p”选项,就可以测试你自定义的配置协议了。当然你也可以通过在你的程序中调用nDPI的APIndpi_load_protocols_file()来测试你的配置。
6 .示例
这节中我们将展示一些demo程序ndpiReader的使用范例。
6.1现场捕获模式
下面这个例子展示了ndpiReader的现场捕获模式,其中“-i”选项用来指定需要进行嗅探的设备接口,“-s”选项指定了嗅探的时间。
$sudo ./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
------------------------------------------------------------
UsingnDPI (2.0.0-838-6607c33) [1 thread(s)]
Capturinglive traffic from device eth0...
Capturingtraffic up to 5 seconds
Runningthread 0...
nDPIMemory statistics:
nDPIMemory (once): 93.13 KB
FlowMemory (per flow): 1.25 KB
ActualMemory: 1.49 MB
PeakMemory: 1.49 MB
Trafficstatistics:
Ethernetbytes: 80367 (includes ethernet CRC/IFC/trailer)
Discardedbytes: 1200
IPpackets: 236 of 256 packets total
IPbytes: 74703 (avg pkt size 291 bytes)
Uniqueflows: 165
TCPPackets: 0
UDPPackets: 230
VLANPackets: 4
MPLSPackets: 0
PPPoEPackets: 0
FragmentedPackets: 0
MaxPacket size: 328
PacketLen < 64: 28
PacketLen 64-128: 9
PacketLen 128-256: 6
PacketLen 256-1024: 193
PacketLen 1024-1500: 0
PacketLen > 1500: 0
nDPIthroughput: 47.22 pps / 125.62 Kb/sec
Analysisbegin: 01/Jan/1970 08:00:00
Analysisend: 01/Jan/1970 08:00:00
Trafficthroughput: 47.22 pps / 125.62 Kb/sec
Trafficduration: 4.998 sec
Guessedflow protos: 1
Detectedprotocols:
Unknown packets: 194 bytes: 69976 flows: 143
NetBIOS packets: 19 bytes: 2116 flows: 8
SSDP packets: 2 bytes: 416 flows: 2
IGMP packets: 2 bytes: 120 flows: 2
ICMPV6 packets: 4 bytes: 344 flows: 1
DHCPV6 packets: 3 bytes: 455 flows: 3
LLMNR packets: 10 bytes: 760 flows: 5
Cloudflare packets: 2 bytes: 516 flows: 1
Protocolstatistics:
Acceptable 4727 bytes
Unrated 69976 bytes
6.2文件捕获模式
最简单的创建一个pcap文件的方法是使用tcpdump命令,就像下面这个例子一项:
$sudo tcpdump -i eth0 -w /var/tmp/capture.pcap -v
tcpdump:listening on eth0, link-type EN10MB (Ethernet), capture size 262144bytes
^C248packets captured
252packets received by filter
0packets dropped by kernel
一旦pcap文件被创建,你就可以像下面这样运行ndpiReader:
$sudo ./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
------------------------------------------------------------
UsingnDPI (2.0.0-838-6607c33) [1 thread(s)]
Capturinglive traffic from device eth0...
Capturingtraffic up to 5 seconds
Runningthread 0...
nDPIMemory statistics:
nDPIMemory (once): 93.13 KB
FlowMemory (per flow): 1.25 KB
ActualMemory: 1.49 MB
PeakMemory: 1.49 MB
Trafficstatistics:
Ethernetbytes: 80650 (includes ethernet CRC/IFC/trailer)
Discardedbytes: 1020
IPpackets: 231 of 248 packets total
IPbytes: 75106 (avg pkt size 302 bytes)
Uniqueflows: 164
TCPPackets: 2
UDPPackets: 227
VLANPackets: 1
MPLSPackets: 0
PPPoEPackets: 0
FragmentedPackets: 0
MaxPacket size: 328
PacketLen < 64: 19
PacketLen 64-128: 6
PacketLen 128-256: 13
PacketLen 256-1024: 193
PacketLen 1024-1500: 0
PacketLen > 1500: 0
nDPIthroughput: 155.03 K pps / 412.96 Mb/sec
Analysisbegin: 14/Dec/2017 15:37:39
Analysisend: 14/Dec/2017 15:37:44
Trafficthroughput: 49.59 pps / 135.25 Kb/sec
Trafficduration: 4.659 sec
Guessedflow protos: 0
Detectedprotocols:
Unknown packets: 200 bytes: 71136 flows: 146
MDNS packets: 6 bytes: 1197 flows: 3
NetBIOS packets: 6 bytes: 552 flows: 3
SSDP packets: 3 bytes: 624 flows: 2
ICMPV6 packets: 1 bytes: 86 flows: 1
DHCPV6 packets: 5 bytes: 761 flows: 5
LLMNR packets: 10 bytes: 750 flows: 4
Protocolstatistics:
Acceptable 3970 bytes
Unrated 71136 bytes
6.3协议文件
为了阐述清楚协议文件的作用,我们现在就来讲解如何识别ntop.org的流量。
可以像下面这样编辑protos.txt.
$echo 'host:"ntop.org"@nTop' > protos.txt
修改完协议文件之后,你就可以像下面这样运行ndpiReader:
$sudo ./ndpiReader -i eth0 -s 30 -p ./protos.txt
7.API nDPI
这节中高亮的就是nDPI的API。
这节中将ndpiReader作为一个基本范例来展示如何初始化nDPI库。首先需要一个编译完成的库以及一个合适的Makefile(i.e就像ndpiReader的Makefile那样)
为了在你的程序中使用nDPI的API,你除了要include自己的头文件外,还需要添加类似下面这一行:
#include<ndpi/ndpi_main.h>
库可以按照下面的顺序执行初始化:
[1].创建并初始化一个nDPI核心库探测模块
structndpi_detection_module_struct * module =ndpi_init_detection_module();
备注:本API格式在Version2.0版本中较之前版本差异很大。
这个探测模块中维护了所有支持的协议。
本API只是注册了所有支持的协议,但并未使能其中任何一个协议
[2].ndpiReader接下来通过一些宏使能了探测模块中的所有协议(显然你可以根据自己的需求来决定使能哪些协议)
NDPI_BITMASK_SET_ALL(all);
ndpi_set_protocol_detection_bitmask2(
structndpi_detection_module_struct *ndpi_struct,
constNDPI_PROTOCOL_BITMASK * dbm);
参数含义如下:
@ndpi_struct指向当前操作的探测模块
@dbm调用者实际通过该集合来控制实际需要应用的协议,只有该字段中被置1的对应协议,其协议分析器才真正允许被加载
备注:本API的作用就是使能一个已经初始化的nDPI核心库探测模块中的协议
[3].为了导入已经存在的协议文件,你还必须调用下面的API
ndpi_load_protocols_file(structndpi_detection_module_struct *ndpi_mod, char* path);
参数含义如下:
@ndpi_mod指向当前操作的探测模块
@path协议文件的路径
[4].一旦从你的pcap文件或设备接口上捕获到了数据流,就可以调用下面的API来进行分析
ndpi_protocolndpi_detection_process_packet(
structndpi_detection_module_struct *ndpi_struct,
structndpi_flow_struct *flow,
constunsigned char *packet,
constunsigned short packetlen,
constu_int64_t current_tick_l,
structndpi_id_struct *src,
structndpi_id_struct *dst)
参数含义如下:
@ndpi_struct指向传入包所属的探测模块
@ndpi_flow指向传入包所属的数据流
@packet指向传入包的IP头
@packetlen IP包的长度
@current_tick_l收到该IP包的时间(ms)
@src指向源用户状态机
@dst指向目的用户状态机
备注:本API是ndpi核心库处理收到包的入口,通过分析传入的IP包,完成数据流的识别,最后返回是别结果.
如果想了解更深入的信息,我们建议你阅读下面这些文件:
nDPI/example/pcapReader.c,
nDPI/src/include/ndpi_structs.h,
nDPI/src/include/ndpi_public_functions.h
nDPI/src/ndpi_main.c.
具体的协议解析器文件都被放在nDPI/src/protocols文件夹中。
上一篇: TCP协议分析(一)