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