基于开源项目nmap的网络拓扑实现源码分析

背景

公司最近在做一个网络类的项目,涉及资产自动发现、绘制网络拓扑图等方面的内容。资产自动发现就是利用nmap来实现的,相对来说比较简单。网络拓扑发现需要较好的网络基础知识,这恰好又是我的弱项。什么SNMP、LLDP、ARP、CIDR等等,看着就比较头疼。Google了不少的实现方案,有基于SNMP和JAVA的,基于nmap和perl的、开源openNMS等,由于各种原因都没能满足自己的需求。最终一次偶然的机会看到zenmap(nmap的图形界面程序,其实这个工具在最开始做资产自动发现的时候就安装过,但是但是不会用,只知道用几个命令扫描,居然没有发现自带的程序都有网络拓扑功能。。。。),经使用发现zenmap的网络拓扑功能符合预期,就找到了该项目的源码,分析其具体实现。

配置开发环境

CentOS虚拟机一台,系统自带python2.7

安装nmap,yum install nmap

下载vscode,使用rpm -ivh code-1.29.1-1542309276.el7.x86_64.rpm命令安装vscode

在vscode安装python插件,新安装的code直接点击extensions,选择python安装

获取项目源码,git clone https://github.com/nmap/nmap.git

zenmap源码分析

zenmap是基于gtk开发的一款图形化的nmap扫描工具,具体使用可以参考nmap官网,下面我介绍一下zenmap源码的具体运行及调试过程:

1、找到程序入口zenmap

zenmap文件存放在{项目目录}/nmap/zenmap/路径下,这是程序的入口文件,我们可以直接在该路径下执行./zenmap或者使用python zenmap来执行该文件,该文件的代码及执行结果如下:

网络拓扑图 虚拟化怎么表示 网络拓扑实现_python

网络拓扑图 虚拟化怎么表示 网络拓扑实现_网络拓扑图 虚拟化怎么表示_02

在target后面输入需要扫描的IP地址或者IP段,如127.0.0.1,192.168.0.1/24等,点击Scan就可以执行扫描了

如果需要以debug模式运行,则在vscode中,打开zenmap文件,选择debug—>python:Current File,进入调试模式

2、配置参数

在command后面加上--traceroute参数,执行扫描,可以获取到路由追踪信息

网络拓扑图 虚拟化怎么表示 网络拓扑实现_nmap python _03

 3、获取活动主机

经过调试发现,在绘制网络拓扑的过程中,需要先获取活动主机信息,该方法位于zenmapCore/NetworkInventory.py文件中

网络拓扑图 虚拟化怎么表示 网络拓扑实现_网络拓扑图 虚拟化怎么表示_04

 经过调试得到活动主机信息,包含nmap扫描出来的一些常规数据,最重要的是加入--traceroute参数扫描以后,得到的主机信息中包含了trace字段,trace里面的rtt和ttl是绘制网络拓扑图的关键

网络拓扑图 虚拟化怎么表示 网络拓扑实现_数据_05

 

网络拓扑图 虚拟化怎么表示 网络拓扑实现_数据_06

4、根据主机信息绘图

绘图过程调用make_graph_from_hosts()方法,该方法位于zenmap/radialnet/util/integration.py,首先需要配置一个根节点main_node,通常情况下就是执行扫描的主机,也就是localhost

网络拓扑图 虚拟化怎么表示 网络拓扑实现_python_07

遍历hosts,定义主节点即main_node,解析trace中的hops,获取每个节点的ttl

网络拓扑图 虚拟化怎么表示 网络拓扑实现_数据_08

创建连接,根据当前node、prev_node、rtt来进行创建

网络拓扑图 虚拟化怎么表示 网络拓扑实现_网络拓扑_09

再次遍历hosts,设置节点信息

网络拓扑图 虚拟化怎么表示 网络拓扑实现_nmap python _10

设置图形节点和主节点

 

网络拓扑图 虚拟化怎么表示 网络拓扑实现_网络拓扑图 虚拟化怎么表示_11

graph数据结构

 

网络拓扑图 虚拟化怎么表示 网络拓扑实现_网络拓扑图 虚拟化怎么表示_12

最后根据graph的数据,使用gtk进行绘图(这一块就没有进一步研究了,因为项目使用的是B/S架构,只要弄清楚网络拓扑发现的实现原理以及获取到想要的数据就可以了,前端实现绘图可以使用go.js、d3等前端框架来实现) 

总结 

在绘图的过程中,主要依据主节点的其他节点中的node_edges以及node_edges中的Edge_weights一一对应形成网络拓扑图的边,其中Edge_weights的值从上述hosts中的rtt获取。

网络拓扑图 虚拟化怎么表示 网络拓扑实现_网络拓扑图 虚拟化怎么表示_13