Last active
May 4, 2018 19:20
-
-
Save kamikat/d4e4206ff3d5d8bfc8db0931c5851a61 to your computer and use it in GitHub Desktop.
Traceroute implementation in Python 2.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python2.7 | |
import argparse | |
import socket | |
import struct | |
import random | |
import time | |
MAX_HOP=64 | |
MAX_ICMP_PACKET_SIZE=1508 | |
class Protocol: | |
def __init__(self, packet): | |
self.packet = packet | |
def shift(self, size): | |
data = self.packet[:size] | |
self.packet = self.packet[size:] | |
return data | |
def probe(addr, ttl, port=60021): | |
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
s.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, ttl) | |
s.sendto("\x00"*16, (addr, port)) | |
def traceroute(host): | |
s_icmp = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) | |
s_icmp.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1) | |
s_icmp.settimeout(5.0) | |
for ttl in xrange(1, MAX_HOP + 1): | |
dport = random.randint(60000, 61000) | |
for i in xrange(3): | |
probe(host, ttl, dport) | |
t0 = time.time() | |
while time.time() - t0 < 5.0: | |
try: | |
ip_packet, addr = s_icmp.recvfrom(MAX_ICMP_PACKET_SIZE) | |
except socket.timeout: | |
continue | |
packet = Protocol(ip_packet) | |
packet.shift(20) # skip IP header | |
t, code, checksum = struct.unpack('!bbH', packet.shift(4)) | |
if t == 11 and code == 0: | |
packet.shift(4) # skip TEM reserved | |
packet.shift(20) # skip IP header | |
udp_sport, udp_dport = struct.unpack('!HH', packet.shift(4)) | |
if udp_dport == dport: | |
yield (ttl, addr[0], time.time() - t0) | |
break | |
else: | |
yield (ttl, None, time.time() - t0) | |
if __name__ == '__main__': | |
parser = argparse.ArgumentParser(description="print the route packets take to network host") | |
parser.add_argument('host', help='destination host') | |
args = parser.parse_args() | |
print "traceroute to %s, %d hops max" % (args.host, MAX_HOP) | |
for hop, addr, rtt in traceroute(args.host): | |
print " %-2s %-15s %9s" % (hop, addr if addr else '*', "%.3fms" % (rtt * 1000) if addr else '') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment