#!/usr/bin/env python3

# This script performs a traceroute *from python*, so you have to give your
# python interpreter CAP_NET_RAW
#
# $ sudo setcap cap_net_raw=eip $(which python3)
#
# Requires geoip2 and an account with them, plus installing Plotly and tsubame

import plotly.express as px
from tsubame import traceroute
import geoip2.webservice
from sys import argv

ACC_NO = "your account number"
ACC_KEY = "your account key"

print(f"Traceroute to {argv[1]}")

ips = []
lats = []
longs = []

with geoip2.webservice.Client(ACC_NO, ACC_KEY, host="geolite.info") as client:
    for hop in traceroute().probe(argv[1], hop_limit=64, count=1, timeout=1.0,
                                ident=None):
        if len(hop) == 0 or hop[0] is None:
            print("****")
            continue

        (ip, delay, done) = hop[0]
        try:
            loc = client.city(ip)
        except geoip2.errors.AddressNotFoundError as e:
            print(f"Hop {ip} is local or not found")
            continue

        print(f"Hop {ip} appears to be at {loc.city.name}, {loc.country.name}")
        ips += [ip]
        lats += [loc.location.latitude]
        longs += [loc.location.longitude]
        if done:
            break

fig = px.line_geo(
        lat=lats,
        lon=longs,
        text=ips)
fig.update_geos(fitbounds="locations")
fig.update_layout(height=900, margin={"r":0, "t":0, "l":1, "b":0})
fig.show()
🗏 Show Raw