MassTraceroute/masstraceroute/__init__.py

114 lines
3.3 KiB
Python
Raw Permalink Normal View History

2021-12-17 18:31:32 +01:00
import threading
import socket
import logging
from random import getrandbits
from time import sleep, time
from multiprocessing.pool import ThreadPool
from multiprocessing import Lock
from threading import Thread
2021-12-17 19:49:26 +01:00
from pprint import pprint
2021-12-17 18:31:32 +01:00
class MassTraceroute:
def __init__(self, socket_timeout, listener_timeout, threads, targets, maxhops):
logging.info("Setting up class")
self.wait = 0.2
2021-12-17 18:51:46 +01:00
self.maxhops = maxhops + 1
2021-12-17 18:31:32 +01:00
self.listener_timeout = listener_timeout
self.socket_timeout = socket_timeout
self.targets = targets
self.threads = threads
self.pool = ThreadPool(processes=self.threads)
self.routes = dict()
2021-12-17 19:49:26 +01:00
for target in self.targets:
self.routes[target] = dict()
2021-12-17 18:51:46 +01:00
logging.info("Creating listener socket")
2021-12-17 18:31:32 +01:00
self.listener = self.init_listener()
self.sources = dict()
2021-12-17 19:49:26 +01:00
self.last_send = time()
2021-12-17 18:31:32 +01:00
def main(self):
logging.info("Starting listener thread")
Thread(target=self.process_listener).start()
logging.info("Starting sender thread")
Thread(target=self.process_sender).start()
def init_listener(self):
listener = socket.socket(
family=socket.AF_INET,
type=socket.SOCK_RAW,
proto=socket.IPPROTO_ICMP
)
listener.settimeout(self.listener_timeout)
listener.bind(('', 0))
return listener
def process_listener(self):
2021-12-17 19:49:26 +01:00
while((self.last_send + self.listener_timeout) > time()):
2021-12-17 18:51:46 +01:00
logging.debug("Listening...")
2021-12-17 18:31:32 +01:00
try:
data, addr = self.listener.recvfrom(1024)
except socket.error as e:
2021-12-17 19:49:26 +01:00
logging.debug(e)
2021-12-17 18:31:32 +01:00
pass
2021-12-17 19:49:26 +01:00
srcport = int.from_bytes(data[48:50], byteorder="big")
dstport = int.from_bytes(data[50:52], byteorder="big")
logging.info("Got data from ip = {}, srcport = {}, dstport = {}, original target = {}, hop = {}".format(addr[0], srcport, dstport, self.sources[srcport]["ip"], self.sources[srcport][dstport]))
2021-12-17 18:31:32 +01:00
if srcport in self.sources and dstport in self.sources[srcport]:
hop = self.sources[srcport][dstport]
ip = self.sources[srcport]["ip"]
2021-12-17 19:49:26 +01:00
self.routes[ip][hop] = addr[0]
logging.info(self.routes[ip][hop])
2021-12-17 18:31:32 +01:00
else:
logging.error("Received package with srcport or dstport non existsant?")
2021-12-17 19:49:26 +01:00
pprint(self.routes)
2021-12-17 18:31:32 +01:00
def process_sender(self):
2021-12-17 18:51:46 +01:00
logging.info("Starting process_sender")
#for target in self.targets:
# self.send(target)
2021-12-17 18:31:32 +01:00
self.pool.map(self.send, self.targets)
def init_sender(self):
sender = socket.socket(
family=socket.AF_INET,
type=socket.SOCK_DGRAM,
proto=socket.IPPROTO_UDP
)
return sender
def send(self, dstip):
2021-12-17 18:51:46 +01:00
logging.info("Entering send()")
sender = self.init_sender()
2021-12-17 19:49:26 +01:00
while(True):
2021-12-17 18:31:32 +01:00
srcport = getrandbits(16)
2021-12-17 19:49:26 +01:00
if srcport not in self.sources:
self.sources[srcport] = dict()
self.sources[srcport]["ip"] = dstip
break
2021-12-17 18:31:32 +01:00
2021-12-17 18:51:46 +01:00
logging.info("Binding sending socket")
sender.bind(('', srcport))
2021-12-17 18:31:32 +01:00
2021-12-17 18:51:46 +01:00
for ttl in range(1, self.maxhops):
sender.setsockopt(socket.SOL_IP, socket.IP_TTL, ttl)
2021-12-17 18:31:32 +01:00
dstport = getrandbits(16)
2021-12-17 19:49:26 +01:00
while(True):
2021-12-17 18:31:32 +01:00
dstport = getrandbits(16)
2021-12-17 19:49:26 +01:00
if dstport not in self.sources[srcport]:
self.sources[srcport][dstport] = ttl
logging.debug("Saved ttl = {}, original ttl = {}, target = {}".format(self.sources[srcport][dstport], ttl, dstip))
break
2021-12-17 18:31:32 +01:00
logging.debug("Sending packet srcport = {}, dstport = {}, ttl = {}, dstip = {}".format(srcport, dstport, ttl, dstip))
sender.sendto(b'', (dstip, dstport))
self.last_send = time()
2021-12-17 18:51:46 +01:00
sender.close()
2021-12-17 18:31:32 +01:00