Python – Traceroute with IP Address, ASN, Organization, Country, City

# Author: Kerry Cordero
# Version: 1.0.5
# Description: This script prompts for an IP or FQDN and will output the IP Address, ASN, Organization, Country, & City

from ipwhois import IPWhois
import re
import subprocess
import ipaddress
from prettytable import PrettyTable
import requests
import socket

# prompt the user for the destination
destination = input("Please enter an IP address or FQDN: ")

# Resolve the IP if FQDN is given
    destination_ip = socket.gethostbyname(destination)
except socket.gaierror:
    print("Invalid FQDN")

# Create a table with PrettyTable
table = PrettyTable()
table.field_names = ["Hop", "IP Address", "ASN", "Organization", "Country", "City"]

# run traceroute and handle output line by line
process = subprocess.Popen(['tracert', '-d', destination], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)

hop = 0
timeout_count = 0
for line in iter(process.stdout.readline, ""):
    if "Request timed out." in line:
        timeout_count += 1
        if timeout_count >= 5:
    timeout_count = 0
    ip_addresses = re.findall(r"\b(?:\d{1,3}\.){3}\d{1,3}\b", line)
    if len(ip_addresses) > 0:
        ip = ip_addresses[0]
        if ip == destination_ip and hop == 0:  # if destination IP, and it's the first hop
            continue  # skip it
        hop += 1
        if ipaddress.ip_address(ip).is_global:
            response = requests.get(f"{ip}")
            data = response.json()

            asn_info = data['as'].split(" ", 1)
            asn = asn_info[0]

            # To fetch organization name, we will use IPWhois
            obj = IPWhois(ip)
            results = obj.lookup_rdap(depth=1)
            org = results['asn_description']

            country = data['country'] if 'country' in data else 'N/A'
            city = data['city'] if 'city' in data else 'N/A'

            table.add_row([hop, ip, asn, org, country, city])
            table.add_row([hop, ip, "N/A", "Private Address", "N/A", "N/A"])