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]}")
@ganti-sharan
Copy link

Hey it just prints * in every hop can you please help

@aalmiramolla
Copy link
Author

@ganti-sharan

Traceback (most recent call last):
File "traceroute.py", line 44, in
dest_name = sys.argv[1]
IndexError: list index out of range

You have to run: python traceroute.py example.com

Hey it just prints * in every hop can you please help

The "*" is because it has no response from the host.

@ganti-sharan
Copy link

It is showing * for every every host what do i do

@ganti-sharan
Copy link

Do you have any idea why it is showing * for every case
Please help
thanks

@aalmiramolla
Copy link
Author

Do you have any idea why it is showing * for every case Please help thanks

It depends on your internet connection. I can't help you with this.

My output to example.com is:

traceroute to example.com
1	192.168.1.1	2090
2	*	2127
3	*	2130
4	--	14557
5	--	12415
6	*	902
7	*	2154
8	--	85877
9	--	129375
10	--	126326
11	--	126312
12	--	126644
13	93.184.216.34	108159

The '--' are valid IP, but obfuscated by me.

@ganti-sharan
Copy link

okay thank you for the help bro is there any way to get 3 rtts instead of 1

@aalmiramolla
Copy link
Author

Yes, you can fork this gist and do a for with this piece of code 3 times:

       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()

@ganti-sharan
Copy link

Any suggestions on what to do to get the results

@aalmiramolla
Copy link
Author

Any suggestions on what to do to get the results

I don't have any idea, sorry

@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