Skip to content

Instantly share code, notes, and snippets.

@aalmiramolla
Forked from inaz2/traceroute.py
Last active June 26, 2024 09:09
Show Gist options
  • Save aalmiramolla/e9cd17a387498fc61b3881c331cc2dc5 to your computer and use it in GitHub Desktop.
Save aalmiramolla/e9cd17a387498fc61b3881c331cc2dc5 to your computer and use it in GitHub Desktop.
Python implementation of traceroute
# references:
# Learning by doing: Writing your own traceroute in 8 easy steps (Ksplice Blog)
# https://blogs.oracle.com/ksplice/entry/learning_by_doing_writing_your
# Edited by: Alejandro Almira <laboral at alejandroalmira.com>
import datetime
import socket
import sys
def traceroute(hostname_or_address, max_hops=30, timeout=2):
dest_addr = socket.gethostbyname(hostname_or_address)
proto_icmp = socket.getprotobyname("icmp")
proto_udp = socket.getprotobyname("udp")
port = 33434
for ttl in range(1, max_hops + 1):
rx = socket.socket(socket.AF_INET, socket.SOCK_RAW, proto_icmp)
rx.settimeout(timeout)
rx.bind(("", port))
tx = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, proto_udp)
tx.setsockopt(socket.SOL_IP, socket.IP_TTL, ttl)
start = datetime.datetime.now()
tx.sendto("".encode(), (dest_addr, port))
try:
_, curr_addr = rx.recvfrom(512)
curr_addr = curr_addr[0]
except socket.error:
curr_addr = "*"
finally:
end = datetime.datetime.now()
rx.close()
tx.close()
yield curr_addr, (end - start).microseconds
if curr_addr == dest_addr:
break
if __name__ == "__main__":
dest_name = sys.argv[1]
print(f"traceroute to {dest_name}")
for i, v in enumerate(traceroute(dest_name)):
print(f"{i+1}\t{v[0]}\t{v[1]}")
@rednafi
Copy link

rednafi commented Jun 2, 2023

Neat. Here's another implementation that's a bit more robust and doesn't create a new socket connection in each loop:

https://rednafi.com/python/implement_traceroute_in_python/#writing-a-crappier-version-of-traceroute-in-python

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment