网络分流器-DPI深度数据包检测

网络分流器-戎腾网络-DPI检测是当前比较流行的网络监控前端的一种模式,而网络分流器对于网络安全的重要性能够说是到头重要的!今天咱们来聊聊DPI检测
网络分流器-DPI深度数据包检测
网络分流器-DPI深度数据包检测前端

深度数据包检测(DPI)git

深度数据包检测(Deep packet inspection,缩写为 DPI)是一种特殊的网络技术,通常网络设备只会查看以太网头部、IP头部而不会分析TCP/UDP里面的内容这种被称为浅数据包检测;与之对应的DPI会检查TCP/UDP里面的内容,因此称为深度数据包检测。
DPI通常是一个硬件或者软件,通常用“旁挂”的方式接入到网络。它会对网络中的每一个数据包进行检查,识别出应用层协议,根据识别的协议采起必定的措施(好比记录HTTP访问行为)。对于TCP协议它能够识别完整的TCP交互过程(好比HTTP请求从请求到响应中间会有屡次TCP数据包发送)。
网络分流器-DPI深度数据包检测
戎腾网络移动互联网采集器支持160个10G和20个100G程序员

nDPI
nDPI是一个C语言编写的DPI库,用来实现软件DPI系统。它是从OpenDPI扩展而来,两者的架构和实现基本上差很少。
编译安装以后它生成/usr/local/lib/libndpi.(a,so)库文件(a静态库文件,so动态连接库);/usr/local/include/会安装相关的头文件。
我我的喜欢用 静态库文件,这样会把全部的二进制代码合并到一个可执行文件中运行的时候不须要安装一大堆库。另外我也不喜欢把东西放到/usr/local/lib下,因此我提供的代码是经过cmake作了一个“all in one”的编译。github上放到是1.6版本的,若是你想更新代码只要替换src文件夹就好了。github

如何用nDPI算法

nDPI的代码写 的很烂,也没有什么架构就是一团乱麻(其实稍微写写都要比这个好)。可是它至少还能正常工做并且是惟一一个“开放”的DPI库,因此不管什么缘由你选择了它都必须忍受它的“丑陋”。
nDPI几乎没有文档说明,只带了一个“ndpiReader”的例子,写的“洋洋洒洒”如行云流水通常(就不吐槽了)。这就是我这篇文章的写做缘由,但愿能给使用nDPI的同窗一点帮助。安全

nDPI最重要的一个数据结构是ndpi_detection_module_struct_t它经过ndpi_init_detection_module构造出来
网络分流器-DPI深度数据包检测
网络分流器
第一个参数用来计算nDPI分析协议的各类超时时间,通常精确到毫秒就能够了1000(nDPI协议分析部分和“全局部分”耦合很是紧,这个数据其实只有“协议分析模块”须要)网络

第二个、三个参数是封装过的“内存分配”函数;nDPI的内存管理很是乱,有些地方是咱们本身申请内存而由nDPI内部帮咱们释放。因此必须nDPI并不直接使用malloc、free之类的申请、释放内存而是交由程序员本身提供函数;数据结构

第三个参数是调试函数,若是定义了NDPI_ENABLE_DEBUG_MESSAGES那么nDPI会调用这个函数输出一些调试信息;架构

全部的nDPI API都是这种“鬼畜”风格,几乎是各类纠结。。。万幸咱们只须要使用不多的API就能够完成任务了。ide

配置协议分析模块

nDPI支持多种协议,都在protocols文件夹中。编译的时候全部协议都会被放到nDPI库中。使用的时候咱们能够本身设置须要开启那些分析模块
网络分流器-DPI深度数据包检测

NDPI_PROTOCOL_BITMASK定义开启协议的“位图”,经过NDPI_BITMASK_ADD函数能够添加支持的协议,最后调用ndpi_set_protocol_detection_bitmask2配置位图。

ndpi_set_protocol_detection_bitmask2函数的第一个参数就是ndpi_detection_module_struct_t(上面咱们初始化的那个数据结构);第二个参数是位图标志。

特别注意:开启的协议越多识别速度越慢;nDPI识别协议的时候是一个串行结构,不管是否被成功是被都会认认真真遍历完咱们配置好的协议

子协议

子协议是某个协议的细分,好比咱们想要分析全部“Google”的HTTP请求那么第一步是分析出“HTTP”请求,第二步是判断HOST包含google.com。这里的第二步就是“子协议”。

nDPI惟一的一份“QuickStartGuide”对这个有进一步解释,子协议识别是以配置文件的方式提供给nDPI的。好比
网络分流器-DPI深度数据包检测

它还支持端口的方式(TCP的8一、8181直接被标记为HTTP再也不作内容检测)

网络分流器-DPI深度数据包检测
网络分流器

nDPI此处的实现使用了一个很是有名的算法—— Aho-Corasick。以第一幅图为例子,里面配置了两条规则“Google”和“Veneer”,咱们有一个字符串(HOST),怎么判断这个字符串符合那个规则呢?最简单的办法是循环全部的规则,若是规则条目不少那么速度会很是慢。Aho-Corasick就是这样一种算法,它能够在O(n)中完成全部的匹配任务。

经过ndpi_load_protocols_file函数加载“子协议”。

开始识别

识别协议的API很是简单——ndpi_detection_process_packet函数。就是这个坑爹的函数,变态程度几乎能够说用使人发指来形容。

ndpi_struct全局的结构体
flow比较特殊,咱们后面讲
packet指向IP头部的指针
packetlen数据包大小
current_tick_l当前时间(精确到毫秒)用于判断“过时的TCP请求”
src,dst其实没有什么用途,文档上说是跟状态机有关其实没有半毛钱关系。惟一的用途是更新“分析协议”的配置。通常设置为NULL就好了
TCP协议是一个流(flow)式的协议,通过从三次握手开始通信双方都是“请求->响应”的结构。DPI能够跟踪其中的一个或者几个数据包,也能够实现所有跟踪(后续我会交叉使用TCP会话、会话、flow,三个名词实际上是同样的)。

nDPI内部不会记录完整的TCP数据包,而是用一个定义很是模糊的ndpi_flow_struct类型来表示一个TCP会话(这个数据结构还包含了“协议分析”部分数据,因此定义很是模糊)。为了便于分析完整的TCP请求咱们定义了一个本身的数据结构dpi_flow_t,ndpi_flow_struct做为它的一个成员。用伪代码表示分析过程:

落到代码上就是get_ndpi_flow函数;实现上咱们会对目标、源端口排序再作hash;这是因为数据包是“相互通信”的因此发送方、接收方是相对而言,不然识别到的多是“一方”的数据。

通常咱们用一个二叉树存放全部正在分析的TCP会话,nDPI移植了FreeBSD中的一组函数ndpi_tfind、ndpi_tsearch、ndpi_twalk、ndpi_tdelete等用来实现经常使用的数据结构操做。
网络分流器-DPI深度数据包检测

相关文章
相关标签/搜索