
Nmap Development mailing list archives
Zenmap idea for Summer of Code 2008
From: Vladimir Mitrovic <snipe714 () gmail com>
Date: Tue, 11 Mar 2008 12:27:20 +0100
Hello everyone,I have an idea for this year's Summer of Code, so I figured I should share it early with you guys. I'm hoping for a chance to work on Zenmap this summer.
I was doing some thinking/research about graphical network topology mapping (or a lack thereof) and how cool it would be if Zenmap had that functionality, so I came up with a simple algorithm and implemented it in Python. I've attached the source code (disclaimer: it's a quick hack), so I'll continue with a brief explanation of the basic ideas behind it.
First, a user supplies an IP address (or an IP range) which is our "destination", and the prefix length (PLEN), which is used for standard CIDR-style subnet scanning (performed later). All IP addresses are added to the "to be processed" (TBP) list.
For every address ADDR in the TBP list, do the following:* Run a traceroute to ADDR, and add any newly-discovered intermediate hosts to the TBP list. Update the topology graph using traceroute's data to add new nodes and construct edges between nodes. * Run a nmap scan on ADDR/PLEN (standard CIDR-style designation) and add any discovered hosts to the TBP list.
When there are no addresses left in the TBP list, the construction of the topology graph is "finished". I say "finished" here because, of course, a user can only see the portion of the net she scanned. What I thought would be cool (but didn't implement it) is that a user should be able to manually expand the constructed topology once the algorithm finishes its run (that's the TODO on stinkfist.py:85). For example, she knows that there's a live host (or hosts) on the local LAN that wasn't detected because PLEN was too big.
There are also some other ideas that can be implemented, for example if a node has more than two edges connected to it, then it's probably a router. Also I had some thoughts about the starting node - maybe it doesn't have to be the localhost, so we can simulate being on some other machine and starting the scan from there. The possibilities are endless... ;)
As for the code, I used (py)graphviz to represent the topology graph and plot it to an SVG image. You can use "stinkfist.py dst TARGET PLEN" (note the "dst" there) or "stinkfist.py dst TARGET" (PLEN = 29, default) to generate the topology file for graphviz (in the form TARGET_PLEN.dot). You can then use "draw.py FILENAME" to convert the .dot file into an .svg image (Firefox can open it). Also attached is a sample scan of my ISP's subnet with PLEN = 29, converted to a GIF image. I've blurred out the first two octets of IP addresses for privacy reasons.
So guys, any input is welcome, and please let me know if I'm reinventing the wheel here. I'm looking forward to discussing this with you.
Cheers, Vladimir p.s. I apologize if the name "stinkfist" sounds bad, it's just a working title.
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import os import re import pygraphviz default_plen = 29 # default topology = pygraphviz.AGraph() startaddr = "localhost" # TODO get a real local IP (ifconfig, whatever) def traceroute(dest): addrlist = [] tr_out = os.popen("traceroute -I -n " + dest + " 2> /dev/null", "r") for line in tr_out: # find the first IP address in the current line addr = re.findall(r'[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+', line) if addr != []: addrlist.append(addr[0]) return addrlist def scan_subnet(subnet): addrlist = [] nmap_out = os.popen("nmap -sP " + subnet + " 2> /dev/null", "r") for line in nmap_out: addr = re.findall(r'[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+', line) if addr != []: addrlist.append(addr[0]) return addrlist def destination_based(dest, plen): ip_list = [] # list of not-yet-processed nodes result_list = [] # list of processed nodes ### 1. traceroute to the destination address print "initial traceroute run:\n " + startaddr, for addr in traceroute(dest): print "-> " + addr, ip_list.append(addr) print # add these nodes to the topology graph if len(ip_list) > 0: topology.add_edge(startaddr, ip_list[0]) # cheat for i in range(0, len(ip_list)-1): topology.add_edge(ip_list[i], ip_list[i+1]) ### 2. for addr in ip_list: result_list.append(addr) ### 2.1 traceroute to the current node, add any new nodes to ip_list print "processing " + addr lastaddr = startaddr for newaddr in traceroute(addr): if newaddr not in result_list and newaddr not in ip_list: ip_list.append(newaddr) # add the new node to the topology graph topology.add_edge(lastaddr, newaddr) lastaddr = newaddr ### 2.2 scan this host's subnet, using a given host width for newaddr in scan_subnet(addr + "/" + str(plen)): if newaddr not in result_list and newaddr not in ip_list: ip_list.append(newaddr) ### 2.3 ### 2.4 #ip_list.remove(addr) # save the topology into a .dot file tfile = dest + "_" + str(plen) + ".dot" topology.write(tfile) print "written topology into " + tfile def incremental(): # TODO implement pass def single_node(): # TODO implement pass if __name__ == "__main__": if sys.argv[1] == "dst": if len(sys.argv) == 4: destination_based(sys.argv[2], sys.argv[3]) else: destination_based(sys.argv[2], default_plen) elif sys.argv[1] == "inc": incremental() elif sys.argv[1] == "scn": scan_subnet(sys.argv[2]) elif sys.argv[1] == "sgl": single_node()
#!/usr/bin/env python # -*- coding: utf-8 -*- from pygraphviz import * import re import sys format = "svg" layout = "dot" #layout = "circo" A = AGraph() A.read(sys.argv[1]) A.layout(layout) A.graph_attr["label"]=sys.argv[1] A.node_attr["shape"] = "circle" # put the format extension instead of the original extension and draw A.draw(re.sub(r'\.\w+$', '', sys.argv[1]) + "." + format)
_______________________________________________ Sent through the nmap-dev mailing list http://cgi.insecure.org/mailman/listinfo/nmap-dev Archived at http://SecLists.Org
Current thread:
- Zenmap idea for Summer of Code 2008 Vladimir Mitrovic (Mar 11)
- Re: Zenmap idea for Summer of Code 2008 Eddie Bell (Mar 11)