-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtracert.py
102 lines (88 loc) · 2.8 KB
/
tracert.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import argparse
import socket
import string
import struct
import re
from sys import platform
from ipaddress import IPv4Address, ip_address
from whois import Information
def main(args):
for address in args.addresses:
if not valid_addr(address):
print("%s is not valid." % address)
continue
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_RAW,
socket.IPPROTO_ICMP)
sock.settimeout(1.5)
trace(socket.gethostbyname(address), sock)
print("FINISHED FOR {address}\r\n".format(address=address))
except KeyboardInterrupt:
print("Stopped")
break
except OSError as e:
if platform == "win32":
win_oserror_handler(e, address)
else:
print(e)
break
def win_oserror_handler(exception, address):
code = exception.errno
if code == 10049:
print("%s is invalid." % address)
elif code == 10013:
print("You should run it with administrator rights.")
else:
print("Unknown return code.")
def valid_addr(address):
try:
ip_address(address)
return True
except ValueError:
try:
socket.gethostbyname(address)
return True
except socket.gaierror:
return False
def trace(address, sock):
max_hops = 30
ttl = 1
port = 54321
buffer = 1536
addr = None
while not (addr == address or ttl >= max_hops):
sock.setsockopt(socket.SOL_IP, socket.IP_TTL, ttl)
sock.sendto(struct.pack("!BBHHH", 8, 0, 26648, 1, 331) +
string.ascii_lowercase.encode(), (address, port))
try:
addr = sock.recvfrom(buffer)[1][0]
if not IPv4Address(addr).is_private:
info = Information(addr)
info.get_info()
print_report(
ttl, addr, info.name, info.as_number, info.country)
else:
print_report(ttl, addr, "local")
except socket.timeout:
print_report(ttl, "*")
ttl += 1
sock.shutdown(0)
sock.close()
def print_report(number, address, name="", as_number="", country=""):
output = "{number}. {ip}\r\n".format(number=number, ip=address)
try:
as_ = re.search("\d+$", as_number).group()
except AttributeError:
as_ = as_number
data = ", ".join([elem for elem in [name, as_, country] if elem])
if data:
output += data + "\r\n"
print(output)
def create_parser():
parser = argparse.ArgumentParser()
parser.add_argument("addresses", help="Addresses you want to trace.",
nargs='*')
return parser
if __name__ == "__main__":
p = create_parser()
main(p.parse_args())