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
Esempio n. 2
0
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
Esempio n. 4
0
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
Esempio n. 5
0
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
Esempio n. 6
0
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
Esempio n. 7
0
def parse_trace_route(tc_string):
    # Parse the traceroute output
    traceroute = trparse.loads(tc_string)
    return traceroute
Esempio n. 8
0
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
Esempio n. 9
0
 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()
Esempio n. 10
0
 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