- changed a few methods to be private
- changed basic constructor so that module could be used on its own aside from command-line
This commit is contained in:
parent
f418b800d6
commit
1c5a84b739
2 changed files with 69 additions and 15 deletions
2
requirements.txt
Normal file
2
requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
netifaces==0.10.4
|
||||||
|
requests==2.7.0
|
||||||
82
traceroute.py
Normal file → Executable file
82
traceroute.py
Normal file → Executable file
|
|
@ -15,10 +15,12 @@ import sys
|
||||||
import urllib
|
import urllib
|
||||||
import urllib2
|
import urllib2
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
|
import requests
|
||||||
|
|
||||||
USER_AGENT = "traceroute/1.0 (+https://github.com/ayeowch/traceroute)"
|
USER_AGENT = "traceroute/1.0 (+https://github.com/ayeowch/traceroute)"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Traceroute(object):
|
class Traceroute(object):
|
||||||
"""
|
"""
|
||||||
Multi-source traceroute instance.
|
Multi-source traceroute instance.
|
||||||
|
|
@ -33,13 +35,23 @@ class Traceroute(object):
|
||||||
sources = json.loads(json_file.replace("_IP_ADDRESS_", ip_address))
|
sources = json.loads(json_file.replace("_IP_ADDRESS_", ip_address))
|
||||||
self.source = sources[country]
|
self.source = sources[country]
|
||||||
self.country = country
|
self.country = country
|
||||||
|
|
||||||
|
if self.country == 'LO':
|
||||||
|
self.local_mode = True
|
||||||
|
self.pub_ip = self._lookup_public_ip()
|
||||||
|
else:
|
||||||
|
self.local_mode = False
|
||||||
|
|
||||||
self.tmp_dir = tmp_dir
|
self.tmp_dir = tmp_dir
|
||||||
self.no_geo = no_geo
|
self.no_geo = no_geo
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
self.locations = {}
|
self.locations = {}
|
||||||
|
self.hops = []
|
||||||
|
|
||||||
def traceroute(self):
|
self._initialize()
|
||||||
|
|
||||||
|
def _initialize(self):
|
||||||
"""
|
"""
|
||||||
Instead of running the actual traceroute command, we will fetch
|
Instead of running the actual traceroute command, we will fetch
|
||||||
standard traceroute results from several publicly available webpages
|
standard traceroute results from several publicly available webpages
|
||||||
|
|
@ -62,16 +74,42 @@ class Traceroute(object):
|
||||||
traceroute = open(filepath, "r").read()
|
traceroute = open(filepath, "r").read()
|
||||||
|
|
||||||
# hop_num, hosts
|
# hop_num, hosts
|
||||||
hops = self.get_hops(traceroute)
|
hops = self._get_hops(traceroute)
|
||||||
|
|
||||||
# hop_num, hostname, ip_address, rtt
|
# hop_num, hostname, ip_address, rtt
|
||||||
hops = self.get_formatted_hops(hops)
|
self.hops = self._get_formatted_hops()
|
||||||
|
|
||||||
if not self.no_geo:
|
if not self.no_geo:
|
||||||
# hop_num, hostname, ip_address, rtt, latitude, longitude
|
# hop_num, hostname, ip_address, rtt, latitude, longitude
|
||||||
hops = self.get_geocoded_hops(hops)
|
self.hops = self._get_geocoded_hops()
|
||||||
|
|
||||||
|
self.hops = map(lambda h: {h.pop("hop_num") : h}, self.hops)
|
||||||
|
|
||||||
|
def get_report(self):
|
||||||
|
report_structure = {}
|
||||||
|
|
||||||
|
report_structure['hops'] = self.hops
|
||||||
|
if self.local_mode:
|
||||||
|
report_structure['pub_ip'] = self.pub_ip
|
||||||
|
|
||||||
|
return report_structure
|
||||||
|
|
||||||
|
def _lookup_public_ip(self):
|
||||||
|
|
||||||
|
#TODO Don't forget to put timeout from above here....
|
||||||
|
response = requests.get('https://api.ipify.org?format=json')
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
ip_data = response.json()
|
||||||
|
if 'ip' not in ip_data.keys():
|
||||||
|
return 'Unable to determine IP'
|
||||||
|
else:
|
||||||
|
return ip_data['ip']
|
||||||
|
else:
|
||||||
|
return 'Unable to determine IP'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return hops
|
|
||||||
|
|
||||||
def get_traceroute_output(self):
|
def get_traceroute_output(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -94,12 +132,11 @@ class Traceroute(object):
|
||||||
traceroute = re.findall(pattern, content)[0].strip()
|
traceroute = re.findall(pattern, content)[0].strip()
|
||||||
return (status_code, traceroute)
|
return (status_code, traceroute)
|
||||||
|
|
||||||
def get_hops(self, traceroute):
|
def _get_hops(self, traceroute):
|
||||||
"""
|
"""
|
||||||
Returns hops from traceroute output in an array of dicts each
|
Returns hops from traceroute output in an array of dicts each
|
||||||
with hop number and the associated hosts data.
|
with hop number and the associated hosts data.
|
||||||
"""
|
"""
|
||||||
hops = []
|
|
||||||
regex = r'^(?P<hop_num>\d+)(?P<hosts>.*?)$'
|
regex = r'^(?P<hop_num>\d+)(?P<hosts>.*?)$'
|
||||||
lines = traceroute.split("\n")
|
lines = traceroute.split("\n")
|
||||||
for line in lines:
|
for line in lines:
|
||||||
|
|
@ -112,17 +149,16 @@ class Traceroute(object):
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
continue
|
continue
|
||||||
self.print_debug(hop)
|
self.print_debug(hop)
|
||||||
hops.append(hop)
|
self.hops.append(hop)
|
||||||
return hops
|
|
||||||
|
|
||||||
def get_formatted_hops(self, hops):
|
def _get_formatted_hops(self):
|
||||||
"""
|
"""
|
||||||
Hosts data from get_hops() is represented in a single string.
|
Hosts data from get_hops() is represented in a single string.
|
||||||
We use this function to better represent the hosts data in a dict.
|
We use this function to better represent the hosts data in a dict.
|
||||||
"""
|
"""
|
||||||
formatted_hops = []
|
formatted_hops = []
|
||||||
regex = r'(?P<h>[\w.-]+) \((?P<i>[\d.]+)\) (?P<r>\d{1,4}.\d{1,4} ms)'
|
regex = r'(?P<h>[\w.-]+) \((?P<i>[\d.]+)\) (?P<r>\d{1,4}.\d{1,4} ms)'
|
||||||
for hop in hops:
|
for hop in self.hops:
|
||||||
hop_num = int(hop['hop_num'].strip())
|
hop_num = int(hop['hop_num'].strip())
|
||||||
hosts = hop['hosts'].replace(" ", " ").strip()
|
hosts = hop['hosts'].replace(" ", " ").strip()
|
||||||
# Using re.findall(), we split the hosts, then for each host,
|
# Using re.findall(), we split the hosts, then for each host,
|
||||||
|
|
@ -139,13 +175,14 @@ class Traceroute(object):
|
||||||
formatted_hops.append(hop_context)
|
formatted_hops.append(hop_context)
|
||||||
return formatted_hops
|
return formatted_hops
|
||||||
|
|
||||||
def get_geocoded_hops(self, hops):
|
|
||||||
|
def _get_geocoded_hops(self):
|
||||||
"""
|
"""
|
||||||
Returns hops from get_formatted_hops() with geolocation information
|
Returns hops from get_formatted_hops() with geolocation information
|
||||||
for each hop.
|
for each hop.
|
||||||
"""
|
"""
|
||||||
geocoded_hops = []
|
geocoded_hops = []
|
||||||
for hop in hops:
|
for hop in self.hops:
|
||||||
ip_address = hop['ip_address']
|
ip_address = hop['ip_address']
|
||||||
location = None
|
location = None
|
||||||
if ip_address in self.locations:
|
if ip_address in self.locations:
|
||||||
|
|
@ -287,6 +324,9 @@ def main():
|
||||||
options, _ = cmdparser.parse_args()
|
options, _ = cmdparser.parse_args()
|
||||||
json_file = open(options.json_file, "r").read()
|
json_file = open(options.json_file, "r").read()
|
||||||
sources = json.loads(json_file.replace("_IP_ADDRESS_", options.ip_address))
|
sources = json.loads(json_file.replace("_IP_ADDRESS_", options.ip_address))
|
||||||
|
|
||||||
|
|
||||||
|
# Get Hope info using Traceroute Object
|
||||||
traceroute = Traceroute(ip_address=options.ip_address,
|
traceroute = Traceroute(ip_address=options.ip_address,
|
||||||
source=sources[options.country],
|
source=sources[options.country],
|
||||||
country=options.country,
|
country=options.country,
|
||||||
|
|
@ -294,8 +334,20 @@ def main():
|
||||||
no_geo=options.no_geo,
|
no_geo=options.no_geo,
|
||||||
timeout=options.timeout,
|
timeout=options.timeout,
|
||||||
debug=options.debug)
|
debug=options.debug)
|
||||||
hops = traceroute.traceroute()
|
"""
|
||||||
print(json.dumps(hops, indent=4))
|
Pseudo-Code
|
||||||
|
|
||||||
|
report = traceroute.get_report()
|
||||||
|
|
||||||
|
print(json.dumps(report, indent=4)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
report = traceroute.get_report()
|
||||||
|
|
||||||
|
|
||||||
|
print(json.dumps(report, indent=4))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue