MassTraceroute/masstraceroute/__init__.py
2021-12-17 19:49:26 +01:00

114 lines
3.3 KiB
Python

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
from pprint import pprint
class MassTraceroute:
def __init__(self, socket_timeout, listener_timeout, threads, targets, maxhops):
logging.info("Setting up class")
self.wait = 0.2
self.maxhops = maxhops + 1
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()
for target in self.targets:
self.routes[target] = dict()
logging.info("Creating listener socket")
self.listener = self.init_listener()
self.sources = dict()
self.last_send = time()
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):
while((self.last_send + self.listener_timeout) > time()):
logging.debug("Listening...")
try:
data, addr = self.listener.recvfrom(1024)
except socket.error as e:
logging.debug(e)
pass
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]))
if srcport in self.sources and dstport in self.sources[srcport]:
hop = self.sources[srcport][dstport]
ip = self.sources[srcport]["ip"]
self.routes[ip][hop] = addr[0]
logging.info(self.routes[ip][hop])
else:
logging.error("Received package with srcport or dstport non existsant?")
pprint(self.routes)
def process_sender(self):
logging.info("Starting process_sender")
#for target in self.targets:
# self.send(target)
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):
logging.info("Entering send()")
sender = self.init_sender()
while(True):
srcport = getrandbits(16)
if srcport not in self.sources:
self.sources[srcport] = dict()
self.sources[srcport]["ip"] = dstip
break
logging.info("Binding sending socket")
sender.bind(('', srcport))
for ttl in range(1, self.maxhops):
sender.setsockopt(socket.SOL_IP, socket.IP_TTL, ttl)
dstport = getrandbits(16)
while(True):
dstport = getrandbits(16)
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
logging.debug("Sending packet srcport = {}, dstport = {}, ttl = {}, dstip = {}".format(srcport, dstport, ttl, dstip))
sender.sendto(b'', (dstip, dstport))
self.last_send = time()
sender.close()