- Graphic traceroute enhanced to cope with TCP, UDP, ICMP or other traceroutes

- ASN clustering in graphic traceroute can be controlled with the "ASN" parameter
This commit is contained in:
pbi 2005-02-20 21:22:23 +00:00
parent b2402037a8
commit 94563e2c0f
1 changed files with 94 additions and 30 deletions

View File

@ -21,6 +21,10 @@
# #
# $Log: scapy.py,v $ # $Log: scapy.py,v $
# Revision 0.9.17.39 2005/02/20 22:22:23 pbi
# - Graphic traceroute enhanced to cope with TCP, UDP, ICMP or other traceroutes
# - ASN clustering in graphic traceroute can be controlled with the "ASN" parameter
#
# Revision 0.9.17.38 2005/02/18 21:03:26 pbi # Revision 0.9.17.38 2005/02/18 21:03:26 pbi
# - MGCP early support # - MGCP early support
# - RandString() # - RandString()
@ -567,7 +571,7 @@
from __future__ import generators from __future__ import generators
RCSID="$Id: scapy.py,v 0.9.17.38 2005/02/18 21:03:26 pbi Exp $" RCSID="$Id: scapy.py,v 0.9.17.39 2005/02/20 22:22:23 pbi Exp $"
VERSION = RCSID.split()[2]+"beta" VERSION = RCSID.split()[2]+"beta"
@ -891,6 +895,10 @@ def strxor(x,y):
def do_graph(graph,type="svg",target="| display"): def do_graph(graph,type="svg",target="| display"):
"""do_graph(graph, type="svg",target="| display"):
graph: GraphViz graph description
type: output type (svg, ps, gif, jpg, etc.), passed to dot's "-T" option
target: filename or redirect. Defaults pipe to Imagemagick's display program"""
w,r = os.popen2("dot -T %s %s" % (type,target)) w,r = os.popen2("dot -T %s %s" % (type,target))
w.write(graph) w.write(graph)
w.close() w.close()
@ -1451,6 +1459,7 @@ class TracerouteResult(SndRcvAns):
def __init__(self, res, name="Traceroute"): def __init__(self, res, name="Traceroute"):
PacketList.__init__(self, res, name) PacketList.__init__(self, res, name)
self.graphdef = None self.graphdef = None
self.graphASN = 0
def display(self): def display(self):
@ -1458,23 +1467,39 @@ class TracerouteResult(SndRcvAns):
lambda x: x[0].ttl, lambda x: x[0].ttl,
lambda x: x[1].sprintf("%-15s,IP.src% {TCP:%TCP.flags%}{ICMP:%ir,ICMP.type%}")) lambda x: x[1].sprintf("%-15s,IP.src% {TCP:%TCP.flags%}{ICMP:%ir,ICMP.type%}"))
def make_graph(self): def make_graph(self,ASN):
self.graphASN = ASN
ips = {} ips = {}
rt = {} rt = {}
ports = {} ports = {}
ports_done = {} ports_done = {}
for s,r in self.res: for s,r in self.res:
ips[r.src] = None ips[r.src] = None
trace_id = (s.dst,s.dport) if s.haslayer(TCP) or s.haslayer(UDP):
trace_id = (s.src,s.dst,s.proto,s.dport)
elif s.haslayer(ICMP):
trace_id = (s.src,s.dst,s.proto,s.type)
else:
trace_id = (s.src,s.dst,s.proto,0)
trace = rt.get(trace_id,{}) trace = rt.get(trace_id,{})
if r.haslayer(TCP): if not r.haslayer(ICMP) or r.type != 11:
if ports_done.has_key(trace_id): if ports_done.has_key(trace_id):
continue continue
ports_done[trace_id] = None ports_done[trace_id] = None
p = ports.get(r.src,[]) p = ports.get(r.src,[])
p.append(r.sprintf("<%TCP.sport%> %TCP.sport%: %TCP.flags%")) if r.haslayer(TCP):
p.append(r.sprintf("<T%ir,TCP.sport%> %TCP.sport%: %TCP.flags%"))
trace[s.ttl] = r.sprintf('"%IP.src%":T%ir,TCP.sport%')
elif r.haslayer(UDP):
p.append(r.sprintf("<U%ir,UDP.sport%> %UDP.sport%"))
trace[s.ttl] = r.sprintf('"%IP.src%":U%ir,UDP.sport%')
elif r.haslayer(ICMP):
p.append(r.sprintf("<I%ir,ICMP.type%> ICMP %ICMP.type%"))
trace[s.ttl] = r.sprintf('"%IP.src%":I%ir,ICMP.type%')
else:
p.append(r.sprintf("<P%ir,IP.proto> IP %IP.proto%"))
trace[s.ttl] = r.sprintf('"%IP.src%":P%ir,IP.proto%')
ports[r.src] = p ports[r.src] = p
trace[s.ttl] = r.sprintf('"%IP.src%":%TCP.sport%')
else: else:
trace[s.ttl] = r.sprintf('"%IP.src%"') trace[s.ttl] = r.sprintf('"%IP.src%"')
rt[trace_id] = trace rt[trace_id] = trace
@ -1490,13 +1515,24 @@ class TracerouteResult(SndRcvAns):
trace[n] = "unk%i" % unk trace[n] = "unk%i" % unk
unk += 1 unk += 1
if not ports_done.has_key(rtk): if not ports_done.has_key(rtk):
bh = '%s:%i' % rtk if rtk[2] == 1: #ICMP
bh = "%s %i" % (rtk[1],rtk[3])
elif rtk[2] == 6: #TCP
bh = "%s:%i/tcp" % (rtk[1],rtk[3])
elif rtk[2] == 17: #UDP
bh = '%s:%i/udp' % (rtk[1],rtk[3])
else:
bh = '%s,proto %i' % (rtk[1],rtk[2])
ips[bh] = None ips[bh] = None
bh = '"%s"' % bh bh = '"%s"' % bh
trace[max(k)+1] = bh trace[max(k)+1] = bh
blackholes.append(bh) blackholes.append(bh)
# Find AS numbers # Find AS numbers
def getASNlist_radb(list):
def parseWhois(x): def parseWhois(x):
asn,desc = None,"" asn,desc = None,""
for l in x.splitlines(): for l in x.splitlines():
@ -1510,19 +1546,42 @@ class TracerouteResult(SndRcvAns):
break break
return asn,desc.strip() return asn,desc.strip()
ASNlist = []
def getASNlist(list): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ASNlist=[] s.connect(("whois.ra.net",43))
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("whois.ra.net",43)) ## whois.cymru.com
for ip in list: for ip in list:
s.send("-k %s\n" % ip.split(":")[0]) s.send("-k %s\n" % ip)
asn,desc = parseWhois(s.recv(8192)) asn,desc = parseWhois(s.recv(8192))
ASNlist.append((ip,asn,desc)) ASNlist.append((ip,asn,desc))
return ASNlist return ASNlist
def getASNlist_cymru(list):
ASNlist = []
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("whois.cymru.com",43))
s.send("begin\r\n"+"\r\n".join(list)+"\r\nend\r\n")
r = ""
while 1:
l = s.recv(8192)
if l == "":
break
r += l
s.close()
for l in r.splitlines()[1:]:
asn,ip,desc = map(str.strip, l.split("|"))
if asn == "NA":
continue
asn = int(asn)
ASNlist.append((ip,asn,desc))
return ASNlist
ASNlist = getASNlist(ips)
if ASN == 1:
ASNlist = getASNlist_cymru(map(lambda x:x.split(":")[0],ips))
elif ASN == 2:
ASNlist = getASNlist_radb(map(lambda x:x.split(":")[0],ips))
else:
ASNlist = []
ASNs = {} ASNs = {}
@ -1598,9 +1657,14 @@ class TracerouteResult(SndRcvAns):
s += "}\n"; s += "}\n";
self.graphdef = s self.graphdef = s
def graph(self, **kargs): def graph(self, ASN=1, **kargs):
if self.graphdef is None: """x.graph(ASN=1, other args):
self.make_graph() ASN=0 : no clustering
ASN=1 : use whois.cymru.net AS clustering
ASN=2 : use whois.ra.net AS clustering
other args are passed to do_graph()"""
if self.graphdef is None or self.graphASN != ASN:
self.make_graph(ASN)
do_graph(self.graphdef, **kargs) do_graph(self.graphdef, **kargs)