Python 100 project #33: Simple Traceroute #2

I modified some lines on previous traceroute on #32.

  • modified break sequence so that it can skip those nodes which are configured not to respond to udp request.
  • added RTT. I tried to use sent_time and time from the scapy itself. But it seems the value is not retirievable and I just ended up using legacy time function to get the idea of RTT(of course this is not reliable, so it’s just an idea)

 

Output Example:

$ python3 ntwk_basetools.py 
1: 192.168.1.1 50 msec
2: 100.64.X.X 18 msec
3: 172.17.2.76 17 msec
4: 172.16.17.192 17 msec
5: 172.16.24.26 22 msec
6: 172.16.25.234 24 msec
7: 172.16.24.82 19 msec
8: 77.67.98.205 17 msec
9: 89.149.142.254 93 msec
10: 216.98.120.41 94 msec
11: 58.138.80.77 161 msec
12: 58.138.88.105 249 msec
13: *
14: *
15: *
16: *
17: *

 

Here is the code:

import time

from scapy.all import *


TIMEOUT = 30

def udptraceroute(hostname):

    result = []
    time_result = []
    for i in range(1, 20):
        pkt = IP(dst=hostname, ttl=i) / UDP(dport=33433 + i)

        start_time = time.time()
        reply = sr1(pkt, verbose=0, timeout=TIMEOUT)
        end_time = time.time()
        result.append(reply)
        time_result.append(end_time - start_time)

        # stop trace if last 5 trial doesn't get reply. consider it's dead end
        if all(response is None for response in result[-5:]):
            break

        # reply.type 3 is port unreachable. hence it's replied by the host itself
        if reply is not None and reply.type == 3:
            break

    return result, time_result


if __name__ == "__main__":
    result, time_result = udptraceroute("www.asahi.co.jp")

    for id, (reply, rtt) in enumerate(zip(result, time_result), start=1):
        if reply is not None:
            print(f"{id}: {reply.src} {int(rtt * 1000)} msec")
        else:
            print(f"{id}: *")