def sendTCP(self, IP, TCP, dest_address, port_list:list, num_sended): #Verificando si se ha llegado al limite de retransmiciones if (num_sended > self.MAX_RETRANS): return #Inicializando contador de paquetes recibidos self.tcp_rcv_list[dest_address] = { 'EVENT': threading.Event(), 'COUNT': 0, 'MAX': len(port_list) } #Recorriendo lista de puertos a enviar TCP for dest_port in port_list: #Campos cabecera TCP TCP.Destination_Port = dest_port TCP.setSequence() #Enviando paquete self.SENDER.sendto(IP.to_bytes() + TCP.to_bytes(IP), (dest_address, dest_port)) #Añadiendo paquetes a la lista de espera if num_sended == 1: self.tcp_wait_list[dest_address][dest_port] = { 'TIME': time(), 'SEND': num_sended } #else: self.tcp_list[dest_address][dest_port]['SEND'] = num_sended #Si no se recibieron los tres paquetes antes de que se venciera el timeout if not self.tcp_rcv_list[dest_address]['EVENT'].wait(timeout=self.TIME_OUT * num_sended): #Obteniendo puertos aun pendientes port_list = self.getPendingPorts(dest_address, port_list, TCP = True) if len(port_list) == 0: return #Retransmitir self.sendTCP(IP, TCP, dest_address, port_list, num_sended + 1)
def detectUDP(self, IP, UDP): #Campos cabecera IP IP.setID() #Variables utiles dest_address = IP.Destination_IP.exploded #Inicializando entrada de las listas self.udp_wait_list[dest_address] = {} #Lista de espera self.udp_ready_list[dest_address] = {} #Lista de sondeados #Creando socket de recepcion SOCKET_RCV = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP) SOCKET_RCV.setblocking(False) #Lanzando hilo de recepcion thread_rcv_finish = threading.Event() #Creando evento para terminar el hilo thread_rcv = threading.Thread( target=self.receiveUDP, name = "RCV UDP: " + dest_address, args=( thread_rcv_finish, SOCKET_RCV, dest_address ) ) thread_rcv.start() #Obteniendo lista de puertos range_ports = iter(range(self.MIN_PORT, self.MAX_PORT)) #Recorriendo lista de puertos while True: #Eligiendo puertos a sondear port_list = self.getPorts(range_ports, self.UDP_SIMULTANEOUS_PORT) #2**16 de 3 en 3. #Si no faltan puertos if port_list == None: break #Enviando UDP a los puertos elegidos. self.sendUDP(IP, UDP, port_list, num_sended = 1) #Esperando finalizacion del hilo de recepcion thread_rcv_finish.set() thread_rcv.join() #Eliminando host de la lista de espera del self.udp_wait_list[dest_address] #Cerrando socket de recepcion SOCKET_RCV.close()
def receiveTCP(self, stop_event:threading.Event, Socket, source_address): while not stop_event.is_set(): #Si hay algo que leer if len(select([Socket], [], [], self.TIME_OUT)[0]): #Si hay algo que leer data, address = Socket.recvfrom(80) #Cabecera IP + Cabecera TCP address = address[0] #Si la direccion ip no es la esperada, saltar iteracion if address != source_address: continue #Obteniendo tiempo de respuesta time_rcv = time() #Desempaquetando IP ip = IP.from_bytes(data) #Desempaquetando TCP tcp = TCP.from_bytes(ip.Data) source_port = tcp.Source_Port #Si el puerto no esta en la lista de espera if source_port not in self.tcp_wait_list[address]: continue #Obteniendo tiempo de envio time_rtt = time_rcv - self.tcp_wait_list[address][source_port]['TIME'] num_sended = self.tcp_wait_list[address][source_port]['SEND'] #Si tiene los flags esperados if (tcp.Flag_SYN and tcp.Flag_ACK) or tcp.Flag_RST: #Notificando la recepcion del paquete self.tcp_rcv_list[address]['COUNT'] += 1 #Aumentando contador de recibidos para esta IP #Si se recibieron todos los paquetes enviados if self.tcp_rcv_list[address]['COUNT'] == self.tcp_rcv_list[address]['MAX']: self.tcp_rcv_list[address]['EVENT'].set() #Activar evento #Eliminando de la lista de espera del self.tcp_wait_list[address][source_port] #Si el puerto esta abierto if tcp.Flag_SYN and tcp.Flag_ACK: #Agregando a lista de puertos como abierto self.tcp_ready_list[address][source_port] = { 'TYPE': 'tcp', 'STATE': PortStates.open, 'SEND': num_sended, 'RTT': time_rtt } #Si el puerto esta cerrado elif tcp.Flag_RST: #Puerto cerrado #Agregando a lista de puertos como cerrado self.tcp_ready_list[address][source_port] = { 'TYPE': 'tcp', 'STATE': PortStates.closed, 'SEND': num_sended, 'RTT': time_rtt }
def receiveICMP(self, type_waited:list, code_waited:list): Socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) stop_event = self.rcv_ICMP_event #Mientras no se notifique la detencion while not stop_event.is_set(): #Esperar por mensajes if len(select([Socket], [], [], self.TIME_OUT)[0]): #Leer mensajes data, address = Socket.recvfrom(80) address = address[0] #Guardando tiempo de recepcion time_rcv = time() #Si es una IP que no esta en lista de espera if (address not in self.udp_wait_list) and (address not in self.tcp_wait_list): continue #Desempaquetando IP e ICMP ip = IP.from_bytes(data) icmp = ICMP.from_bytes(ip.Data) #Si no es del tipo y codigo esperado if (icmp.Type not in type_waited) and (icmp.Code not in code_waited): continue if icmp.Type == 3: #Desempaquetando paquete original ip_origin = IP.from_bytes(icmp.Data) #Si fue recibido en respuesta a mensaje UDP if ip_origin.Protocol == socket.IPPROTO_UDP: self.rcv_ICMP_UDP(icmp, UDP.from_bytes(ip_origin.Data), address, time_rcv) #Si fue recibido en respuesta a mensaje TCP elif ip_origin.Protocol == socket.IPPROTO_TCP: self.rcv_ICMP_TCP(icmp, TCP.from_bytes(ip_origin.Data), address, time_rcv) #Si se notifico la detencion if stop_event.is_set(): Socket.close()
def receiveUDP(self, stop_event:threading.Event, Socket, source_address): while not stop_event.is_set(): #Si hay algo que leer if len(select([Socket], [], [], self.TIME_OUT)[0]): #Si hay algo que leer data, address = Socket.recvfrom(80) #Cabecera IP + Cabecera UDP address = address[0] #Si la direccion ip no es la esperada, saltar iteracion if address != source_address: continue #Obteniendo tiempo de respuesta time_rcv = time() #Desempaquetando IP ip = IP.from_bytes(data) #Desempaquetando UDP udp = UDP.from_bytes(ip.Data) source_port = udp.Source_Port #Si el puerto no esta en la lista de espera if source_port not in self.udp_wait_list[address]: continue #Obteniendo tiempo de envio time_rtt = time_rcv - self.udp_wait_list[address][source_port]['TIME'] num_sended = self.udp_wait_list[address][source_port]['SEND'] #Notificando la recepcion del paquete self.udp_rcv_list[address]['COUNT'] += 1 #Aumentando contador de recibidos para esta IP #Si se recibieron todos los paquetes enviados if self.udp_rcv_list[address]['COUNT'] == self.udp_rcv_list[address]['MAX']: self.udp_rcv_list[address]['EVENT'].set() #Activar evento #Eliminando de la lista de espera del self.udp_wait_list[address][source_port] #Agregando a lista de puertos como filtrado self.udp_ready_list[address][udp.Destination_Port] = { 'TYPE': 'udp', 'STATE': PortStates.open_filtered, 'SEND': num_sended, 'RTT': time_rtt }
def to_bytes(self, IP_H:IP): Checksum = self.Checksum if (Checksum == None): #Obteniendo pseudocabecera IP Pseudo_IPHeader = IP_H.getPseudoHeader(self.Length) #Obteniendo copia de objeto UDP UDP_COPY = self.copy() UDP_COPY.Checksum = 0 # 0 para forzar el calculo del checksum #Calculando checksum (Pseudo cabecera IP + Cabecera UDP + Datos) Checksum = Tools.Checksum(Pseudo_IPHeader + UDP_COPY.to_bytes(None)) #Empaquetando segmento y devolviendolo return struct.pack("!HHHH", self.Source_Port, # 2 Bytes -> 16 bits self.Destination_Port, # 2 Bytes -> 16 bits self.Length, # 2 Bytes -> 16 bits Checksum # 2 Bytes -> 16 bits ) + self.Data
def to_bytes(self, IP_HEADER:IP): Checksum = self.Checksum if (Checksum == None): #Longitud del segmento TCP (Cabecera + Datos) Length = self.Header_Length + len(self.Data) #Obteniendo pseudocabecera IP Pseudo_IPHeader = IP_HEADER.getPseudoHeader(Length) #Obteniendo copia objeto TCP y modificando campos TCP_COPY = self.copy() TCP_COPY.Checksum = 0 #Forzar el calculo del checksum #Calculando checksum (Pseudo cabecera IP + Cabecera TCP + Datos) Checksum = Tools.Checksum(Pseudo_IPHeader + TCP_COPY.to_bytes(None)) #Empaquetando segmento y devolviendolo return struct.pack("!HHLLBBHHH", self.Source_Port, # 2 Bytes -> 16 bits self.Destination_Port, # 2 Bytes -> 16 bits self.Sequence, # 4 Bytes -> 32 bits self.Sequence_ACK, # 4 Bytes -> 32 bits (int((self.Header_Length / 4)) << 4), # 1 Bytes -> 4 bits + 4 bits sin usar ( # 2 bits sin usar (self.Flag_URG << 5) + # 1 bits (self.Flag_ACK << 4) + # 1 bits (self.Flag_PSH << 3) + # 1 bits (self.Flag_RST << 2) + # 1 bits (self.Flag_SYN << 1) + # 1 bits (self.Flag_FIN) # 1 bits ), self.Announced_Window, # 2 Bytes -> 16 bits Checksum, # 2 Bytes -> 16 bits self.Urg_Pointer, # 2 Bytes -> 16 bits ) + self.Data
IP_RECEIVE_NAME = socket.gethostbyaddr(IP_RECEIVE[0])[0] except socket.herror: #Si la IP no tiene asociada ningun nombre, entonces guardamos "-" IP_RECEIVE_NAME = '-' #Imprimiendo la IP y el nombre (si lo tiene) del que envio el ICMP, mas el RTT de cada respuesta. print("{} ({})\t\t{}\n".format(IP_RECEIVE[0], IP_RECEIVE_NAME, [str(n) + " ms" for n in timer])) #Imprimiendo informe avanzado if (ADVANCED_MODE == True and len(packets) > 0): print(" Paquetes de respuesta (IP):") #Recorriendo la lista que contiene cada paquete IP recibido anteriormente. for packet in packets: ip = IPPacket( packet ) #Obteniendo un objeto de la clase IP, que se encarga de #separar cada campo del paquete IP. #Imprimiendo campos mas relevantes del paquete IP actual. print( " {} | ( {} => {} )\tVersion = {} , ID = {} , Longitud datagrama = {} , DF = {} , MF = {} , TTL = {}" .format( packets.index(packet) + 1, ip.getSourceAddress(), ip.getDestinationAddress(), ip.version, ip.identificador, ip.longitud_trama, ip.DontFragment, ip.MoreFragment, ip.TTL)) #Guardando en la lista, el paquete ICMP contenido dentro de este paquete IP. packets_icmp.append(ip.Data)