第一次写技术相关的博客,不足之处还请担待并告知。
在开始之前,先简单介绍一下NetAnalyzer, NetAnalyzer是一款集网络数据采集、报文协议分析、统计、网络流量监控于一体的网络管理工具软件,你可以直接认为NetAnalyzer就是中文(简化)版的Wrishark,哈哈,有点夜郎自大了,不过不要在意这些细节。
接下来看看我在代码中的一段注释:
1 /* 2 * 项目开始时间:2011-09-17 3 * 2.0发布时间: 2011-10-04//扬帆起航 4 * 2.1发布时间: 2011-10-20//成长之旅 5 * 2.1.3.10发布时间: 2011-12-06//软件发布 6 * 2.2.0.11发布时间:2011-12-23 //三站点同时发布 7 * 2.4 扩展 8 * 2.5 实用性 9 * 2.8 广泛性 10 * 2.9 初步商业级别 11 * 2.10 建立完整的软件环境 12 * 作者:冯天文 13 * 14 */
注意,该项目是从2011年09月开始的,而且版本是从2.0开始,,这是为什么呢?且听我慢慢道来, 很久很久以前……
1 NetAnalyzer之前的技术积累
刚学JAVA程序设计,因为老师的讲解并不是很彻底,很多东西都需要自己去找资料学习,于是便找到了一些教学视频,通过视频来学习JAVA,在讲到Socket通信时,讲解人就顺便说了一些网络传输数据包的问题,虽然自己是网络专业,但自己只是大一的学生,好多东西都感觉很高深,这也算是第一次接触网络抓包的概念。2010年下半年开始进入了大二,开始有了一点写程序的功底,每天都乐此不疲的写着一些小玩具,但从来不曾做出一款值得炫耀的东西,这种状态持续了很长一段时间。大概是在9月份左右,班上一位朋友偶然看到我在写程序,于是让我加入他们组去参加一个比赛,他当时正在找人,我毫不犹豫就答应了。就在国庆前夕,学院老师给出了几个课题,有分形图设计,有物联网的,也有P2P对等交换技术的,当然还有网络协议编程的,因为考虑到我们自己的专业性,于是选择了网络协议编程,并且给每个团队分配一个指导老师,在与老师的谈话中了解到,我们暂时要做一个基于Winpacp的简单网络嗅探器。
1.1 最原始的数据采集程序
记得当时自己很兴奋,因为当时听起来,如果制作出这样一款软件的确有着很大的成就感。然而完事开头难,虽然已经大二了,但是还没有开设关于网络的专业课,所以一切关于网络的概念都是零,于是发扬老传统,在网上找相关的资料自己学习,国庆期间推掉了一切出行计划,早晨早早就起来,从网络基础开始学习,因为知识触及太广了,很多都看的似懂非懂,然而自己还是坚持下来,当假期结束后,已经有点头绪了,并且学会简单的使用一些网络协议分析工具如:Wireshark,Sniffer等,并结合已经学到的知识,也能做一些简单的协议分析了。
貌似一切都可以开始了,于是开始去尝试看Winpcap的开发文档,记得当时看到的时候感觉一团糟,示例代码是用C写的,其中无论函数名称,还是变量名称都感觉很别扭,不过还是大概可以看得明白。首先自然是从获取网卡的开始,那还是比较短的示例代码,按照文档上面的提示,花了差不多两天的时间才配置好环境,终于将那段代码调试通,当网卡的信息显示在那黑黑的控制台上时,特别激动。
于是快马加鞭调试出了数据采集的控制台程序。但是显示的数据全是原始的数据,只是用十六进制的方式展示出来,如果只是显示出来并没用多大的意义,我需要把这些数据保存下来,并且需要把这些信息分析出来,于是马上改写了程序将这些数据以文本的方式将获取的网络信息写在文件中。然后使用C#做了一个字符串解析的工具,来分析这些数据,该解释工具通过启动进程的方式,启动控制台程序采集数据,并将其保存在文本文件中,然后再将文件加载入解释器中,分别提取个字段进行分析。该解释器,已经提取了以太网中三个字段的的数据:目标MAC,源MAC,上层协议类型等数据。
图1.2被鄙视的文本解释工具
当完成了这个工具,兴致勃勃的让老师看的时候,却完全被无情的鄙视了一通,然而我却固执的认为这个小工具还是有意义的,至少让自己在数据采集设计上迈出了一大步。虽然后来做了很多数据采集的工具,但这个始终保留在自己写的数据采集工具文件夹中。这个小工具的采集数据的程序是唯一用C写的,也真正是按照自己理解的方式运作的。然而现在想来,这却是当时的无奈之举。因为学完的JAVA,感觉在做Windows桌面程序,并不是很好,于是自学了C#,这也可以解释我为什么会使用C#作解释器的问题了。其实开始是想过使用C++通过MFC来制作的,但如果再重新去学习一门语言,入门可能不是难事,但如果要达到得心应手的地步却需要慢慢的积累,不假以时日是不可能的,而坚持自己做的原有的那个肯定是不可以的,整个又陷入了两难境地。
1.2 SnifferSharp的发展
有一天,抱着试试看的心情,在网上找看看是否有有人提供相关的技术支持。于是发现了分装了Winpcap的.Net类库SharpPcap,该库是将Winpcap提供的接口利用.Net技术进行了分装,从而可以直接在C#中应用。
接下来所有的开发都转移到.Net平台上了,并且马上找到了开发者的开发文档,虽然都是英文,不过花了几天的时间整体还是可以看得懂的,文档中提供了相关示例代码,真是柳暗花明又一村,新一轮的编程马上开始,不过有了上次的教训,这次做就有一定的经验了,并且有文档的帮助,做起来也有了底气,于是经过十几天的构建终于第一个可以称之为数据抓包软件snifferSharp v0.5版本终于完成了,该软件基于SharpPcap3.3版本,该软件已经实现了
图1.3 snifferSharp v0.5软件
最初的目标,而且增加了协议的解析,软件中设置专用的结构来提取数据包的协议字段,因为当时自己的知识层次的限制,所以只提取了一些简单的字段进行分析,并将其显示在一个文本框中,方便用户使用,该种设计方式,曾对后来多款软件的有很深的影响。因为使用过Sniffer pro 和Wrieshark其中有一个十六进制显示的窗口,故而,在该软件中也开辟了十六进制显示窗口,程序提供了过滤表达式的配置功能,方便用户捕获特定的数据。在后来的软件在该软件上所列出的各种功能都变为基础配置。
当然该软件中有很多不合理的设计,程序中用一个2百万的数组来缓存捕获的数据,这直接导致内存分配不合理,当时其实意识到这一点而已,还是因为技术水平的问题,未使用动态数组。另一个是因为UI配置与数据存储之间是直接执行的,及数据在存储完成之后,再提取数据包信息,其实后来除了NetAnalyzer2.0及其之后的所有版本都存在这个问题。在UI显示,这是需要时间的,而这段时间内软件将不能采集数据,这样造成丢包率极大,并且数据提取采用循环等待方式,造成CPU消耗很大。还有一个很重要的问题就是,用于显示采集数据的是WinForm中的ListView控件,每当用数据到来时,该控件都要重回,这也是造成丢包的重要原因之一。
在之后的几天里马上完成了snifferSharp v1.0版本,有了前一版本的铺垫,本次并没有在原有的基础上改变什么,只是增加了流量监控功能,在该软件中,添加了自己开发的Chart组件,在NetAnalyzer2.X的版本中依然使用该组件,当然,这个仪表盘已经完全被取代了,而整个组件也由原来的一个,发展为11种,方便各种应用。而在snifferSharp v1.5中针对ListView影响数据采集速度的问题,将程序设置为在捕获数据包的时候先不在界面显示,当单击按钮停止时,再开始在UI显示。此方法类似于Sniffer Pro的处理方式。然而该种方法虽然对数据采集有一定的帮助,但如果采集数据过多,则不得不等待数据的缓慢的在UI上显示。反而不利于数据的即时处理,于是用户不得不花更多的时间去等待数据的解析。
图1.4 snifferSharp v1.0软件
![](https://i-blog.csdnimg.cn/blog_migrate/e0cbe7f5b072c5fe9435b37f7de2967a.png)
1.3 CSniffer的构建
通过snifferSharp系列版本的设计,整个网络数据采集工具的基础架构已经呈现出来,然而伴随而来的整体的表现不尽人意。需要重新架构,包括数据存,UI回显等很多急需要处理的问题。于是自己放弃了继续开发snifferSharp的计划,转而构建了一个全新的数据采集软件系统,这就是CSniffer。该系列软件只出了一个版本,但是,在自己数据采集软件开发过程中却有着非常重要的意义,因为该种设计方案,包括设计思想,UI设计,在NetAnalyzer中可以找它到影子。
![](https://i-blog.csdnimg.cn/blog_migrate/87f404142025e0829e036cfa1bcd268f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2217f245e304e9ae8f44ee6697069db1.png)
本次还增加了对用于层载荷数据的恢复,其实这也是一次实验而已,然而当看到效果是,还是有点小成就。这项功能,在后来几经修改后也成了基本配置,到此为止。再后来的NetAnalyzer开发中都有迹可循了。
对于本次的开发虽然是全新的架构,然而依然摆脱不了那些根深蒂固的问题,数据采集效率虽有所提升,可是空间依然很小。而且在设计中,依然使用了原有软件的协议分析结构,所以报文首部解析,如以往一样,整体表现平平。
本次设计的另一个创新点,就是增加了报文类型分布统计功能。但是因为该功能的增加反而更加影响了软件采集数据的效率,但是该功能还是被保留下来了。因为总会有办法来处理的。这也成为后来NetAnalyzer着重要解决的问题之一。
至此NetAnalyzer之前的所有自己制作的网络数据采集软件全部介绍完成了,事实上包括测试等各种数据采集软件不止这些,因为在制作过程中或修改或删除,只保留了比较典型的几款,也算是比较典型的的几款作为NetAnalyzer发展路上的奠基者。事实上世界上所有的事情都是从无到有,再从有到经典,“不积跬步,无以至千里;不积小流,无以成江海。”如果没有以上这些软件的支撑,自己独立设计NetAnalyzer恐怕只是纸上谈兵的事情。从开始感觉高深莫测,到完成一个不是程序的程序,由原来漏洞百出,到一个可以构成完整体系的框架,以至于现在我需要编写相关的说明来辅助管理整个系统,这不只是软件的发展,更是自己的技术的提升,认识的飞跃。站在今天的角度上,感觉以前的软件确实有不少瑕疵纰漏,而且整个程序都谈不上设计,再看看现在完成的NetAnalyzer感觉是尽善尽美。也许有一天再回过头来看看现在的软件是,也许和现在看以前的程序一样吧。也许这样会显得很悲观,但是只有看到程序软件的不足,才是真正的进步,也才有发展的空间。
2 NetAnalzer的开始
在完成了CSniffer之后,准备要接着进入第二个版本的时候,小组需要一款抓包软件来完成课题。于是就停止了对CSniffer的开发,而进入正是进入了一个新的开发阶段。如果按照软件工程的角度,如自己这般乱来肯定是不可以的,说是一个新的开发阶段,实际上就是重建一个解决方案,简单完成了界面设计就急急忙忙开始了编码,并没有进行完整的设计分析,所幸整个过程已经轻车熟路了,马上就完成了基础编码, 而且整个软件还是比较简单所以用了查不到一个礼拜的时间就完成了软件的设计,本次设计使用了大量的新技术,并且设计出了NetAnalyzer的标准UI,规定了必须要提供的窗口布局位置,而且采用分页方式分别展示软件的主界面与数据处理界面,基本上把CSniffer中实现的四个页面的内容放置在两个页面内,增加了版面的利用率。
![](https://i-blog.csdnimg.cn/blog_migrate/501704ea512a483969f877223497b2fd.png)
相对于UI设计,这次更注重性能的提升,首先自然考虑的是网络数据采集效率的问题,在之前的软件中,这始终是一个无法逾越的鸿沟。然而本次软件设计很大程度上已经解决了该问题,本次数据获取由原来一直使用的循环监听方式变为事件触发通知方式,这样在没有数据报文到来的情况下,整个系统开销减小,当有数据当来,则通知对应的数据存储结构提取数据,这样使数据保存更为灵活,其他线程调用数据时也不会有太大的影响。在界面显示方面该软件摒弃了冲毁频率极高的ListView控件,改为缓冲很小的控件。NetAnalyzer1.X版本的采用分层方式,数据采集于数据分析并不在同一个界面,当数据采集完成之后,将其提交给协议分析界面,不过后来发现,在该界面显示数据的同时,主界面也在同步显示数据,后来发现是因为传值是应用类型的问题,所以在第二版本中取消了该种方式。
图1.8 NetAnalzyer1.3数据采集界面
本次另一个特点就是完善了载荷数据的提取,提供了不同编码方式的转换,考虑到该软件应用于网络层与传输层,于是并没有花更多的时间去处理应用层协议的数据提取功能。本次数据包分析依然使用最初的分析结构,但是对其中的结构做了一些调整,使其更加符合协议中的分布。
NetAnalyzer的第一个版本是在2011年1月初做的,后来陆续做了一点小修改,直至9月一直在使用该版本,而在功能方面,近乎少的可怜,其实在此期间一直打算重新构建NetAnalyzer但一直停留在头脑中。后来重新设计念头是因为假期在和老师做项目的时候,发现自己的一些软件设计方法,有很大的问题,如:急于编码,不做前期分析,软件层次模糊,数据抽象能力不够等。这也让自己意识到软件开发的真正意义。
在9月份中旬开始了NetAnalyzer第二版的前期设计,在总结了上个版本的基础上,规划了架构方式,本次使用组件方式来处理处理不同的任务。当然这次还是没有写文档,只是做了一点小小的规划就开始,这也是后来整个软件越来越不好维护的原因。过再后来的设计中逐步又分离出了了一些组件,从而降低了资源的占用率。并将某些组件制作为独立的工具,供系统外直接调用,如流量监控工具,编码转换工具,应用层协议配置工具等,而对于一些组件则需要在不同的工具中或主系统中被调用,所以将这些也以组件的方式分离出来,供给不同的工具使用,如:过滤表达式配置对话框,异常信息发送对话框等。
图1.9 NetAnalyzer2.2主界面
图1.10 NetAnalyzer2.2 数据分析界面
而事实上,目前已经实现的好多功能并不在开始设计的计划之内,然而随着时间的积累,与自己对种种需求的分析,故不断的增加了相关的功能,在软件工程中,在开始制作软件的时候是要做需求分析,然而自己因为并没用这样的条件,故所增加的功能都只是自己使用的过程中而逐渐发现的,其实曾经在制作版本中增加了用户留言功能,以方便用户回传自己的想法,然而后来在考虑到安全问题,便放弃了(后面会讲到),当然在最新的版本中已经解决了安全问题。
第二版本的NetAnalyzer已经完全脱离了抓包软件的概念,按现在的构建结构,整个可以称之为系统环境。因为本次的设计除了最初目标的网络数据采集,协议分析等,增加流量监控,后台数据采集,编码转换等一系列辅助工具,对于流量监控,虽然曾经出现过,但是,在本次的设计中,流量监控已经成了一个独立的体系,随着流量记录文件的加入,该工具已经可以独立使用了。
图1.11网络流量监控工具
通过文件方式记录网络状态,则需要专用的文件解释器处理相关的数据,因为解释器与流量监控工具大同小异故在此不做截图。
另一个可以独立使用的工具则是编码转换工具,给工具在一开始只是为了辅助主系统完成TCP重组之后处理转换载荷数据编码问题而设立的工具。再后来多次斟酌下最终以独立工具的方式提供使用,而在主系统中则是通过提供接口而启动传值的。这样可以方便不同情况使用。该工具提供了Base64 、URL、HTML、等编码与解码方法,并且提供ASCII、GB2312、UTF-8、Unicode等字符编码方式,在最新版本中增加了MD5消息摘要功能,可分别对字符串和文件进行摘要信息提取。
图1.12 编码工具
对一些共享使用的组件这里只是用过滤表达式配置窗口说明,该组件并不能独立执行,需要加载在其他工具之上,它只提供数据通信接口,与调用方式,该配置窗口提供两种方式,直接输入方式和填写方式,直接输入方式,适合于熟悉Winpcap过滤表达式格式的人员,这样可以写出功能复杂的过滤表达式,在界面上提供了表达式设置规则的链接,对于不懂的用户也可以直接学习使用。而填写方式则适合入门级人员,通过几个选项,输入指定的一些参数,则可自动生成表达式,使用方便,但只能生成简单是表达式,但可以满足一般需求。在完成后点击“确定”按钮,系统开始自动检查表达式是否符合规范。不是则提示用户重新设置,如果是则传入需要的位置,并将该表达式做历史记录,以供下次使用,而表达式输入框对一些关键字进行了着色处理,通过不同颜色标示不同的原语,防止设置出错和方便出错检查。
图1.13 过滤表达式配置
关于NetAnalyzer的简介到此为止,然而则仅仅是序章。而我们也仅仅触及其冰山一角。在上面的介绍中,主要侧重了系统的整体的部分,再后来介绍了一些工具组件等,也只是停留在表面上而已,虽然现在人们越来越注重用户体验,但作为一款给专业人员使用的软件,更应该注重的是效率与可用性。在后面的讲解中我们将逐步将这些功能的实现方式展示出来,从而在原理上深入MetAnalyzer。
总结
“玉不磨,不成器”,软件开发更是如此,在网络数据采集工具开发过程中,从概念到一个影响,再到一个原始实体,最后到一个完整的软件,并非朝夕之功,在大约一年半的时间中,自己全身心投入,不断的改进,不断的寻找解决方案,也许进展缓慢,但是至少每次在自己手中产生的工具都比上一个强,这就是进步。其实不是这次硬逼着自己写这本书,自己还真不知道自己尽力了如此之多的困难,如果当时没那么高的热情去投入其中或满足于现状,也许就没有后续的版本,更没有这本书的产生。
NetAnalyzer而今已经是2.9的版本,而上一次的发布是2014年的9月份,功能相比当时已经丰富了很多,能力也强大了很多,但是更新也越来越慢了,再从2013年6月大学毕业之后只发布了两个简单的版本,也许是工作的忙碌,也许是只是少了那份狂热的追求,以至于现在虽然有很多想法,却也只停留在想象之中,而马上2015年的9月也来了,特地发一个系列去纪念一下那年的热情。