def analyze_traceroutes(current_tr: str, previous_tr: str, rtt_detection_threshold: int = 0): """ Analyses two traceroutes for diffent hops, also checks for rtt increase Returns list of different hops and increased rtt times :param current_tr: (str) raw traceroute output :param previous_tr: (str) raw traceroute output :return: (list) list of different indexes, or where rtt difference is higher than detection threshold """ try: current_tr_object = trparse.loads(current_tr) except trparse.InvalidHeader: logger.warning('Cannot parse current tr') return None, None try: previous_tr_object = trparse.loads(previous_tr) except trparse.InvalidHeader: logger.warning('Cannot parse previous tr') return None, None max_hops = max(len(current_tr_object.hops), len(previous_tr_object.hops)) different_hops = [] increased_rtt = [] for index in range(max_hops): # Try to spot different hop hosts try: if not current_tr_object.hops[index].probes[ 0].ip == previous_tr_object.hops[index].probes[0].ip: different_hops.append(current_tr_object.hops[index].idx) except IndexError: try: different_hops.append(current_tr_object.hops[index].idx) except IndexError: different_hops.append(previous_tr_object.hops[index].idx) # Try to spot increased rtt if rtt_detection_threshold != 0: try: # Try to detect timeouts that did respond earlier if current_tr_object.hops[index].probes[ 0].rtt is None and isinstance( previous_tr_object.hops[index].probes[0].rtt, Decimal): increased_rtt.append(current_tr_object.hops[index].idx) # Try to detect increses in rtt elif current_tr_object.hops[index].probes[0].rtt > ( previous_tr_object.hops[index].probes[0].rtt + rtt_detection_threshold): increased_rtt.append(current_tr_object.hops[index].idx) except (IndexError, TypeError): pass return different_hops, increased_rtt
def traceroute_from_ns(namespace): namespace = util.process_namespace(namespace, allow_none=True) dest = request.args.get("destination") if app.simulate: if dest == "1.1.1.1": return jsonify( { "destination_ip": "1.1.1.1", "destination_name": "host", "hops": [ { "index": 1, "probes": ["host (1.1.1.1) 0.013 ms", "host (1.1.1.1) 0.003 ms", "host (1.1.1.1) 0.003 ms"], } ], } ) else: return jsonify({}) else: try: result = util.run_in_ns(namespace, ["traceroute", dest]) parsed = trparse.loads(result) hops = [] for hop in parsed.hops: probes = [] for probe in hop.probes: probes.append(str(probe).strip()) hops.append({"index": hop.idx, "probes": probes}) traceroute = {"destination_name": parsed.dest_name, "destination_ip": parsed.dest_ip, "hops": hops} return jsonify(traceroute) except subprocess.CalledProcessError as e: LOGGER.exception("status: %s, out: %s, err: %s", e.returncode, e.stdout, e.stderr) return jsonify({})
def list_targets(include_tr: bool = False, formatting: str = 'console'): with db_scoped_session() as db: output = [] targets = crud.get_targets(db=db) for target in targets: groups = crud.get_groups_by_target(db=db, target_id=target.id) traces = get_last_traceroutes(target.name, limit=2) try: current_tr = traces[0] current_tr_object = trparse.loads(current_tr.raw_traceroute) current_rtt = float(current_tr_object.global_rtt) # TypeError may happen if the traceroute could not be done, hence global.rtt does not contain an int type str except (trparse.ParseError, TypeError): current_rtt = None try: previous_tr = traces[1] previous_tr_object = trparse.loads(previous_tr.raw_traceroute) previous_rtt = float(previous_tr_object.global_rtt) except (IndexError, trparse.ParseError, TypeError): previous_tr = None previous_rtt = None target = { 'id': target.id, 'name': target.name, 'address': target.address, 'groups': [group.name for group in groups], 'current_rtt': current_rtt, 'previous_rtt': previous_rtt, 'last_probe': current_tr.creation_date } if include_tr: if previous_tr: target['current_tr'] = format_string( traceroutes_difference_preformatted( current_tr, previous_tr), formatting) else: target['current_tr'] = format_string( current_tr.raw_traceroute, formatting) output.append(target) return output
def traceroute(target): # I was gonna do this in Scapy but I value my Sanity. print "{+} Running traceroute on %s" %(target) trdata = commands.getoutput("traceroute %s" %(target)) parse = trparse.loads(trdata) ipaddrs = [] for hop in parse.hops: probe = hop.probes[0] ipaddrs.append(probe.ip) return ipaddrs
def traceroute(target): # I was gonna do this in Scapy but I value my Sanity. print "{+} Running traceroute on %s" % (target) trdata = commands.getoutput("traceroute %s" % (target)) parse = trparse.loads(trdata) ipaddrs = [] for hop in parse.hops: probe = hop.probes[0] ipaddrs.append(probe.ip) return ipaddrs
def traceroute(domain, method="udp", cmd_arguments=None, external=None, log_prefix=''): """ This function uses centinel.command to issue a traceroute command, wait for it to finish execution and parse the results out to a dictionary. :param domain: the domain to be queried :param method: the packet type used for traceroute, UDP by default :param cmd_arguments: the list of arguments that need to be passed to traceroute. :param external: :param log_prefix: :return: """ # the method specified by the function parameter here will # over-ride the ones given in cmd_arguments because # traceroute will use the last one in the argument list. _cmd_arguments = [] logging.debug("%sRunning traceroute for " "%s using %s probes." % (log_prefix, domain, method)) results = {"method": method} if cmd_arguments is not None: _cmd_arguments = copy.deepcopy(cmd_arguments) if method == "tcp": if platform in ['linux', 'linux2']: _cmd_arguments.append('-T') elif platform == "darwin": _cmd_arguments.append('-P') _cmd_arguments.append('tcp') elif method == "udp": if platform in ['linux', 'linux2']: _cmd_arguments.append('-U') elif platform == "darwin": _cmd_arguments.append('-P') _cmd_arguments.append('udp') elif method == "icmp": if platform in ['linux', 'linux2']: _cmd_arguments.append('-I') elif platform == "darwin": _cmd_arguments.append('-P') _cmd_arguments.append('icmp') cmd = ['traceroute'] + _cmd_arguments + [domain] caller = command.Command(cmd, _traceroute_callback) caller.start() if not caller.started: if caller.exception is not None: if "No such file or directory" in caller.exception: message = "traceroute not found or not installed" else: message = ("traceroute thread threw an " "exception: %s" % caller.exception) elif "enough privileges" in caller.notifications: message = "not enough privileges" elif "not known" in caller.notifications: message = "name or service not known" else: message = caller.notifications results["dest_name"] = domain results["error"] = message if external is not None and type(external) is dict: external[domain] = results return results forcefully_terminated = False timeout = 60 start_time = time.time() # check every second to see if the execution has stopped while caller.thread.isAlive(): if (time.time() - start_time) > timeout: caller.stop() forcefully_terminated = True break time.sleep(1) # we are only accurate down to seconds, so we have # to round up time_elapsed = int(time.time() - start_time) output_string = caller.notifications try: parsed_output = trparse.loads(output_string) except Exception as exc: results["dest_name"] = domain results["error"] = str(exc) results["raw"] = output_string if external is not None and type(external) is dict: external[domain] = results return results hops = list() for hop in parsed_output.hops: hop_json = {"index": hop.idx, "asn": hop.asn} probes_json = [] for probe in hop.probes: probes_json.append({"name": probe.name, "ip": probe.ip, "rtt": probe.rtt, "anno": probe.anno}) hop_json["probes"] = probes_json hops.append(hop_json) results["dest_name"] = parsed_output.dest_name results["dest_ip"] = parsed_output.dest_ip results["hops"] = hops results["forcefully_terminated"] = forcefully_terminated results["time_elapsed"] = time_elapsed # the external result is used when threading to store # the results in the list container provided. if external is not None and type(external) is dict: external[domain] = results return results
def parse_trace_route(tc_string): # Parse the traceroute output traceroute = trparse.loads(tc_string) return traceroute
def traceroute(domain, method="udp", cmd_arguments=None, external=None, log_prefix=''): """ This function uses centinel.command to issue a traceroute command, wait for it to finish execution and parse the results out to a dictionary. :param domain: the domain to be queried :param method: the packet type used for traceroute, UDP by default :param cmd_arguments: the list of arguments that need to be passed to traceroute. :param external: :param log_prefix: :return: """ # the method specified by the function parameter here will # over-ride the ones given in cmd_arguments because # traceroute will use the last one in the argument list. _cmd_arguments = [] logging.debug("%sRunning traceroute for " "%s using %s probes." % (log_prefix, domain, method)) results = {"method": method} if cmd_arguments is not None: _cmd_arguments = copy.deepcopy(cmd_arguments) if method == "tcp": if platform in ['linux', 'linux2']: _cmd_arguments.append('-T') elif platform == "darwin": _cmd_arguments.append('-P') _cmd_arguments.append('tcp') elif method == "udp": if platform in ['linux', 'linux2']: _cmd_arguments.append('-U') elif platform == "darwin": _cmd_arguments.append('-P') _cmd_arguments.append('udp') elif method == "icmp": if platform in ['linux', 'linux2']: _cmd_arguments.append('-I') elif platform == "darwin": _cmd_arguments.append('-P') _cmd_arguments.append('icmp') cmd = ['traceroute'] + _cmd_arguments + [domain] caller = command.Command(cmd, _traceroute_callback) caller.start() if not caller.started: if caller.exception is not None: if "No such file or directory" in caller.exception: message = "traceroute not found or not installed" else: message = ("traceroute thread threw an " "exception: %s" % caller.exception) elif "enough privileges" in caller.notifications: message = "not enough privileges" elif "not known" in caller.notifications: message = "name or service not known" else: message = caller.notifications results["dest_name"] = domain results["error"] = message if external is not None and type(external) is dict: external[domain] = results return results forcefully_terminated = False timeout = 60 start_time = time.time() # check every second to see if the execution has stopped while caller.thread.isAlive(): if (time.time() - start_time) > timeout: caller.stop() forcefully_terminated = True break time.sleep(1) # we are only accurate down to seconds, so we have # to round up time_elapsed = int(time.time() - start_time) output_string = caller.notifications try: parsed_output = trparse.loads(output_string) except Exception as exc: results["dest_name"] = domain results["error"] = str(exc) results["raw"] = output_string if external is not None and type(external) is dict: external[domain] = results return results hops = list() for hop in parsed_output.hops: hop_json = {"index": hop.idx, "asn": hop.asn} probes_json = [] for probe in hop.probes: probes_json.append({ "name": probe.name, "ip": probe.ip, "rtt": probe.rtt, "anno": probe.anno }) hop_json["probes"] = probes_json hops.append(hop_json) results["dest_name"] = parsed_output.dest_name results["dest_ip"] = parsed_output.dest_ip results["hops"] = hops results["forcefully_terminated"] = forcefully_terminated results["time_elapsed"] = time_elapsed # the external result is used when threading to store # the results in the list container provided. if external is not None and type(external) is dict: external[domain] = results return results
def load(self, e_hops, output): self.e_hops = e_hops self.e_num_hops = len(e_hops) self.traceroute = trparse.loads(output) self.vroute()
def load(self, e_hops, output): self.e_hops=e_hops self.e_num_hops = len(e_hops) self.traceroute = trparse.loads(output) self.vroute()
import trparse trFile = './sample_tr.log' trFileHdl = open(trFile, 'r') trString = trFileHdl.read() trFileHdl.close() # Parse the traceroute output traceroute = trparse.loads(trString) # You can print the result print traceroute # Save it as string tr_str = str(traceroute) # Or travel the tree hop = traceroute.hops[0] probe = hop.probes[0] # And print the IP address print probe.ip