Table of Content


IP packet has a TTL field where TTL is an acronym for time-to-live. A forwarding node decrements the TTL value in the packet and then forward it, or drop it when the TTL value becomes 0 and reply the source with a ICMP Time-Exceeded message.

Trace Route

Knowning how a router decrements the TTL value and response to a packet with the 0 TTL value, we can design a trace route program to figure out routers between a source and a destination node. You can actually implement it using with a few different protocols. If you are sending UDP datagrams, you have a UDP traceroute; if you are sending out a TCP SYN segments, you have a TCP traceroute; and if you are sending out ICMP packet, you have a ICMP traceroute.

Below is an ICMP traceroute program in Python using ScaPy. Let’s call this program

import sys
from scapy.layers.inet import IP
from scapy.layers.inet import ICMP
from scapy.sendrecv import sr1
from socket import gethostbyname

def print_route(hops, reply):
    nonemsg = '*****None******'
    unreachmsg = '*****None******'
    hopmsg = 'hops'
    typemsg = 'ICMP msg type '
    if hops == 1:
        hopmsg = 'hop'
    if reply is None:
        src = '*****None******'
        rtype = 'OOPS'
        typemsg = ''
    elif reply.type == 3:
        src = '**Unreachable**'
        rtype = reply.type
        src = reply.src
        rtype = reply.type

    print(f'{hops:2d} {hopmsg:4} away from {src:15} [{typemsg}{rtype:2}]')

    if not reply is None and reply.type == 0:
        print ('Desitnation reached')
def icmp_trace_route(dst):
    dstaddr = gethostbyname(dst)
    noops = 0
    print(f'Traceroute to {dst} at {dstaddr}:')
    for i in range(1, 65): # try 1 hops to 64 hops
        # prepare a ICMP packet (what type of ICMP message is it)?
        pkt = IP(dst=dstaddr, ttl=i) / ICMP()
        # Send the packet and get a reply
        reply = sr1(pkt, verbose=0, timeout=5)
        if reply is None:
            noops = noops + 1
            print_route(i, reply)
            if noops >= 5:
        elif reply.type == 0:
            print_route(i, reply)
        elif reply.type == 3:  # Destination Unreachable  (RFC 792)
            print_route(i, reply)
        elif reply.type == 11: # Time Exceeded (RFC 792)
            print_route(i, reply)
        else:  # Hi friend, How are you configured? Why am I getting this?
            print_route(i, reply)

def main(argv):
    if len(argv) < 2:
        print('Usage: ' + argv[0] + ' destination')
    dst = sys.argv[1]
    nodes = icmp_trace_route(dst)

if __name__=='__main__':


Below are some examples.

  1. Trace route to
    sudo python
  2. Trace route to
    sudo python
  3. Trace route to
    sudo python

Exercise and Exploration

  1. Trace route to a few of your favorite web sites. Is there anything notable that you observe?
  2. How do we revise the program to do a UDP tracerroute instead? What have you tried? What do you observe from your exploration?

Appendix I. Guessing Hosting Locations from IP Addresses

Knowing location of a host is useful to an array of application, such as, positioning you to a nearest geographical point of interest, like a supermarket or a coffee shop when you visit the supermarket’s website or use the coffee shop’s mobile app. There have emerged vendors providing service to determine host locations of IP addresses. A host’s geographical location and its IP address assignment are dynamic and proprietary. The locations have accuracy varying across a number of dimensions, such as, ISP and countries. So, unless you are the ISP or the ISP shares with you the locations, these are a best effort guess.

The following example is to guess the geographical locations of the IP addresses returned from the traceroute experiments, which may provide you with an insight on the scale of the global Internet.

The example uses’s RESTful Web service to guess the locations of the IP addresses. So, your first step is to sign up for a free developer account for an API KEY at With the API KEY, one can issue 1,000 requests a day at present. To run the following program replace the string YOUR_API_KEY with your actually API KEY.

It is worthy of comparing the get_geo_loc() function in the following program with the main() function in, which reveals that that we write the program by revising the program since the following program is actually a Web client to a RESTful Web service.

from http import client as httpclient
import json
import sys

HOST = ''

def build_request(ip):
    request = '/ipgeo?apiKey=' + API_KEY + '&ip=' + ip + '&output=json'
    return request
def get_geo_loc(ip):  
    request = build_request(ip);
    conn = httpclient.HTTPSConnection(HOST)
    conn.request('GET', request)  
    response = conn.getresponse()  
    if response.status != 200:
        location = (False, response.status, json.loads(
        location = (True, response.status, json.loads(
    return location

def main():
    ips = [line.strip() for line in sys.stdin]
    for ip in ips:
        success,_,location = get_geo_loc(ip)
        if not success:
            print(ip, location['message'])
            print(ip, location['latitude'], location['longitude'])

if __name__ == "__main__":    
    # execute only if run as a script


The takes in a list of IP addresses one IP address a line from the Stadndard Input while the prints out the routes on the Standard Output. Given these, we run and in a pipelined fashion as in the following example where we trace route to,

python > facebook_route.txt
grep "hop" facebook_route.txt | grep hop tr.txt | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]" > facebook_route_ip.txt
python < facebook_route_ip.txt > facebook_route_loc.txt

You should take a look at the output files, like facebook_route_loc.txt.

Appendix 2. Mapping Routes

Next step is to put the routes on the map if we know each node’s latitutde and longitude. Python has a few packages to plot maps. The is to plot the route on a map generated using the gmplot package, a Python wrapper of the Google Map API, a JavaScript API.

Preparing Environment

On the virtual machine you’ve beening doing the trace route experiment and getting the route’s locations, install pip3 and gmplot by following the steps below,

sudo apt-get install --no-install-recommends python3-pip
sudo pip3 install gmplot --upgrade

import sys
from gmplot import GoogleMapPlotter 

def get_ip_locs():
    locs = [line.split() for line in sys.stdin]

    lat_list = [float(loc[1]) for loc in locs]
    lon_list = [float(loc[2]) for loc in locs]
    lbl_list = [loc[0] for loc in locs]

    lat_center = sum(lat_list)/len(lat_list)
    lon_center = sum(lon_list)/len(lon_list)

    return lat_list,lon_list,lbl_list,lat_center,lon_center

def main(map_html_fn):
    lat_list,lon_list,lbl_list,lat_center,lon_center = get_ip_locs()

    gmap = GoogleMapPlotter(lat_center, lon_center, 13)

    gmap.scatter(lat_list, lon_list, '#3B0B39', size=200, marker=False ) 
    for lat,lon,lbl in zip(lat_list,lon_list,lbl_list):
        gmap.text(lat, lon, color='#3B0B39', text=lbl)
    gmap.plot(lat_list, lon_list,  'cornflowerblue', edge_width = 2.5)

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print('Usage: YOUR_MAP_NAME.html')

Running and Viewing the Map

  1. First, we generate the map using the output obtained by running in Appendix I as follows,
    grep -v bogon facebook_route_loc.txt | python facebook_route_gmap.html

    where facebook_route_gmap.html contains the map.

  2. How do we view the map? We rely on Python’s built-in Web server. First, take a note of the IP address of the virtual machine,
    ip address show

    Let’s assume the IP address is Then we proceed to the next step.

  3. In the directory where the map html file is, run
    python -m http.server

    Below is an example including output,

    brooklyn@midwood:~$ python -m http.server
    Serving HTTP on port 8000 ( ...

    which shows that the Web server listens to incoming connections at end point

  4. Finally, on the host (e.g., Windows or Mac), point your favorite Web browser, like Firefox, Chrome, or Safari to something like, where the host in the URL is because it is the IP address of the virtual machine we took note of, the map file is the file we generated using

Ignore whatever Google Map complains. Zoom out or in the map. Do you see anything interesting?