深入nDPI

前言

随着日益增加的网络应用数量,在网络上的流量种类越来越多,像QoS、安全性等方面的挑战,传统的方法已经开始乏力。比如P2P应用的带宽占用、使用随机端口的恶意网络应用等,过去单单基于IP、端口的工具很难识别这类应用的流量,因此有必要对报文进行深度解析,这就是DPI技术的必要性。

作为一个开源的DPI工具,nDPI不仅对多种主流协议进行支持,还能避免因随机端口导致的误判,本文就先介绍nDPI的部分技术细节,最后我们通过实践体验nDPI。

nDPI技术细节

nDPI从OpenDPI发展而来,当初OpenDPI只有付费版才有高级特性支持,nDPI作为开源软件提供了和OpenDPI一样的功能。在设计上,nDPI和OpenDPI是差不多的:
1.都是基于C的实现
2.一个两层的架构:核心库用来处理数据包,抽取基本信息;解析器用插件实现,用于解析报文检测协议类别。

和OpenDPI相比,改变了什么

由于OpenDPI存在一些问题,nDPI作为功能超集解决了那些问题:

1.OpenDPI在针对不同协议的插件中,针对协议的数据结构是静态的,比如在一个插件中,某些用来保存特征的变量都绑定到一个具体的值,导致检测协议时受限。

2.nDPI确保报文协议一旦被识别出来就返回结果。但是OpenDPI,即时已经有识别成功,仍会做额外的识别工作导致开销增加。

3.nDPI实现了对加密流量的解析,毕竟如果DPI工具没有办法处理加密流量其实作用甚微。

4.OpenDPI需要加信号量避免同一时间有多个实例修改同一数据。nDPI实现了线程安全。

5.改变OpenDPI的某些奇葩设计:比如每一个流都执行很多初始化工作。nDPI仅需要在startup阶段初始化一次,降低额外开销。

6.优化匹配的方式:nDPI根据端口尝试直接用一些有可能识别成功的协议解析器进行解析,如果猜错了,则按注册顺序用其他解析器解析。比如一个使用22端口的流,OpenDPI并不会尝试先用ssh解析器解析,而是用全部解析器解析一遍直到有一个解析成功(第2点说过,就算有一个识别成功,但也还会继续解析直到所有解析器都过一遍,的确是非常愚蠢的做法)。

7.过于死板的解析器机制:OpenDPI要求每一个支持的协议都要实现一个解析器,然而当用户在使用非标准端口用常规应用的时候就难以识别了。比如定义一个使用TCP承载的X协议,使用端口Y,其实只要改进一下支持在运行时进行配置,TCP解析器支持就可以做到对X协议的支持。这有点像docker image,用户下载一个基本镜像,自定义后保存为新的镜像,就可以满足不同环境的需求。但是OpenDPI做不到,想支持新的应用?自己用C语言写个解析器吧!

8.对提取流的元数据的支持。

nDPI除了解决了上述问题,还增加了通过利用已经识别的url来判断应用的功能,像那些会连接到固定服务器的应用,比如QQ等,这样一来对流的识别效率会有一定程度的提高。针对某些互联网应用,比如Dropbox,由于应用会连接到具体的服务器上(*.dropbox.com),通过解析HTTP头抽取Host字段,如果这个字段的内容和预先设置的url匹配,就可以初步判断为流属于dropbox。

可移植性

nDPI适合作为一些用于检测流量并判断流量属于何种应用的高层应用程序的基础,具有较好的移植性,现在有针对Linux、Windows、Mac和BSD类系统的支持,硬件架构上支持x86,MIPS和ARM。

如何注册一个新的协议

nDPI中,每一个支持的协议都要用一个唯一的数字和一个名称注册、定义。下面通过一个例子介绍下:

用来注册的具体代码是https://github.com/ntop/nDPI/blob/dev/src/include/ndpi_protocol_ids.h

可以看到代码中用宏定义定义了所有支持的协议:

而所支持的又分为三类:protocol、content、service:

看看yahoo这个例子,在ndpi_protocol_ids.h文件中的第118行,定义了一个叫NDPI_PROTOCOL_YAHOO的宏,其值为70:

这个宏会在yahoo.c文件中用到:

高层应用

nDPI要求调用它的高层应用需要提前处理好网包的第二层,由nDPI处理第三层和以上的数据,如果用户使用nDPI作为底层,那么就有必要进行先协议切分,三层和以上的数据才能由nDPI处理。

性能

nDPI解析流的流程是:

1.高层应用把三、四层的数据交给nDPI

2.nDPI根据默认端口和承载协议尝试猜应用协议,并使用猜出来的协议解析器尝试解析,如果解析成功,返回结果;如果不成功,就下一步

3.根据承载协议使用该承载协议分类下的全部协议解析器按顺序尝试解析(比如流是基于TCP,就用和TCP有关的解析器解析,而不会考虑UDP的),如果成功,返回结果;不成功,就下一步

4.上一步不成功的原因可能是协议不被支持或者没有抓到关键的包,如果协议不被支持就会停止解析,如果是后面一种情况就继续等待高层应用提供新的数据(出现这种情况的主要原因是流开始了但没有抓到前面的关键的包,从而导致识别失败)

但是这里有个问题,怎样才知道哪些包重要,哪些不重要,不然让高层应用怎么抓?

流使用不同的承载协议还有某些软件在开始传输数据之前会进行协商或者其他的处理,这些都是可以作为参照的流量特征。参考libprotoident,它用来进行识别的包都是双向流的前面的包,一般而言,用双向流整个周期(流的开始到结束)前面的包来进行识别成功率会更高,笔者的机器学习流量分类研究也是采用了一个双向流的TCP三次握手后的第一个包来作为分类依据。

影响DPI引擎的性能的因素主要是支持的协议数量和流的元数据的抽取,因为在识别流程中,nDPI先根据端口或者url猜可能的协议种类并用对应的解析器尝试解析,如果猜不对就按照解析器的注册顺序解析直到有一个解析成功;另外对于某些流有很多特征元数据的话,抽取特征也是个很耗时的工作。

nDPI的设计中,每个解析器都会包含一个默认的协议和端口。
比如一个TCP流使用80端口的话,nDPI就会尝试猜应用层协议,并尝试使用HTTP解析器解析,如果正好猜对,就能让整个解析过程变得更快,如果猜错(比如HTTP流不用80端口),才会交给其他解析器处理。

加密流量

nDPI针对加密流量一般是两种方法:
1.通过url识别应用类别:不过默认情况下这个仅对互联网应用有效,常见的互联网应用都会连接到其官方服务器,提前注册了这些服务器的url,如果加密流量与这些url有关,就判断流属于与那些url相关的应用。

2.发现自签名的ssl证书:如果是VPN应用,通常使用了自签名的证书而且保持长时间连接,而非像HTTPS一样只发送少量数据。这部分的流识别只能靠行为识别。

扩展

前面提到过可以在运行时自定义协议解析器。使用的时候,需要按照一定的格式写配置文件,这些配置文件主要起到保存特征的作用,比如定义一个基于TCP,使用81端口的流为HTTP,那么nDPI就会从流中提取出某些有用的元数据,通过Aho-Corasick算法进行快速匹配,如果匹配成功,就可以认为这个流使用了HTTP。

简单安装试用

上面讲了技术细节那么久,接下来就简单地介绍下如何单独安装最新的nDPI。

由于官方的QuickStartGuide比较久(13年的),因此不应该参考那个文档。

先从github下载nDPI的源码:

安装配置、编译需要的软件。我的系统中已经安装了GCC和build-essential就只需安装下面的软件:

进入目录执行autogen.sh:

上一步成功后,然后configure和make,用make install安装:

编译完成后,键入ndpiReader就可以看到帮助信息:

尝试使用ndpiReader抓eth0的包持续30秒,看看我们能抓到什么结果:

从这个ndpiReader的说明可以看到,这个工具只是用来展示nDPI的特性,所以读者如果想进一步使用nDPI,还需要更进一步的开发。

由于本人使用ssh连接这个系统,所以只能检测到ssh协议。

关于nDPI的简单入门,请读者参考官网(http://www.ntop.org/support/documentation/documentation/)的nDPI文档,不过文档较旧。

结语

笔者认为,nDPI是个相当不错的开源DPI工具,但是某些地方可能还需要改进,比如针对加密流量还有文档。

针对加密流量可能需要引入SSL卸载技术,以进行更全面的检测和控制。

关于文档,实际上能用来参考如何对nDPI进行二次开发或者基于nDPI开发应用的文档几乎很少或者没有,不知官方是出于何种原因不提供详细的开发者文档,一个开源项目连文档都不全的话不能说是一个好的开源项目,如果要进行二次开发,恐怕要阅读源码梳理过才能着手开发,门槛实在不低。

关于性能,有兴趣的读者可以去找找测试性能的方法,对nDPI的准确率和性能做一个调查。

本文介绍了nDPI的主要技术细节,最后展示了编译、试用的操作。希望本文能为那些有意使用nDPI进行DPI引擎开发的读者有所帮助。因为官方文档不多也有点旧,希望这篇文章能让更多的读者了解到这个工具。本人水平有限,如有缺点和漏洞,还请各位读者指出。

参考:
ntop.org,nDPI - Quick Start Guide

L. Deri, M. Martinelli, A. Cardiglianon,nDPI: Open-Source High-Speed Deep Packet Inspection

作者简介:
何智刚,2015至今,暨南大学经济统计学专业16届新生,主要研究云计算、SDN、机器学习,对各种领域都有所涉猎,目标是迈向full stack。
qq:1097225749
github:https://github.com/Hochikong


  • 本站原创文章仅代表作者观点,不代表SDNLAB立场。所有原创内容版权均属SDNLAB,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用,转载须注明来自 SDNLAB并附上本文链接。 本站中所有编译类文章仅用于学习和交流目的,编译工作遵照 CC 协议,如果有侵犯到您权益的地方,请及时联系我们。
  • 本文链接https://www.sdnlab.com/17449.html
分享到:
相关文章
条评论

登录后才可以评论

Hochikong 发表于16-07-22
2