def packet_received(self, packet, **kwargs): if packet.flags == ACK: #directly remove do not put to closed unblock_outgoing_packets('tcp', None, None, self.session.remoteIP, self.session.remotePort) self.session.unregister_upper_layer(self.session.connectionID) self.session._unregister_app_layer(self.session.connectionID) self.session.switch_state(State_CLOSED(self.session)) else: print "would have sent a reset"
def packet_received(self, packet, **kwargs): if packet.flags == FIN: self.session.switch_state(State_TIME_WAIT(self.session)) #?? #Directly remove the session do not switch to closed unblock_outgoing_packets('tcp', None, None, self.remoteIP, self.remotePort) self.session.unregister_upper_layer(self.session.connectionID) self.session._unregister_app_layer(self.session.connectionID) self.session._send_ACK(packet) self.session.switch_state(State_CLOSED(self.session)) else: self.session.sendRST(packet, **kwargs)
def connect(self, ip, port): #Ajouter support du dns """ This method try to connect to the given ip and port. If the TCP session is not CLOSED the operations are aborted. Else a local port is generated, an entry is added in iptables to preven the kernel to disturbe our connection and then a SYN packet is sent. Then the connection state is switched to SYN_SENT. The method will then loop for 20 seconds checking if the state has changed to ESTABLISHED. If not it means that a problem occured and everything is rolled back. """ if isinstance(self.state, State_CLOSED): self.localPort = random.randrange(1200, 65535) self.remoteIP = ip self.remotePort = port if not re.match(self.ipregex, ip): #Then this is a dn realip = transversal_layer_access["DNS"].nslookup(ip) if realip: self.remoteIP = realip else: raise Exception( "[Errno -5] No address associated with hostname") #starting from here remoteIP contains the destination IP not DN or whatever block_outgoing_packets('tcp', None, None, self.remoteIP, port) self.connectionID = ( self.remoteIP, self.remotePort, self.localIP, self.localPort ) #Switch order because we are interested in receiving incoming packet so src dst is switch self.lowerLayers["default"].register_upper_layer( self.connectionID, self) self._send_SYN() self.switch_state(State_SYN_SENT(self)) #---- Wait for the connection to be established ---- exponential_backoff_values = [ 3 * pow(2, x) for x in range(self.syn_retries) ] #Precompute waiting intervals for timeout in exponential_backoff_values: instant = time.time() while (instant + timeout > time.time()): if isinstance(self.state, State_ESTABLISHED): return True self._send_SYN() #We have not received syn/ack so rollback connection unblock_outgoing_packets('tcp', None, None, self.remoteIP, port) self.lowerLayers["default"].unregister_upper_layer( self.connectionID) return False #No connection can occur if port is not open, arp request failed.. #---------------------------------------------------- else: print("Not in consistent state (" + str(self.state) + ")") return False
def packet_received(self, packet, **kwargs): if packet.flags == FIN: self.session.switch_state(State_FIN_WAIT_2(self.session)) #self.session.packet_received(packet.payload) #Can there be data in a FIN packet ? elif _has_flags(packet.flags, FIN+ACK): #Received FIN and Ack in the same packet self.session._send_ACK() self.session.switch_state(State_TIME_WAIT(self.session))#?? #Directly remove the session do not switch to closed unblock_outgoing_packets('tcp', None, None, self.session.remoteIP, self.session.remotePort) self.session.unregister_upper_layer(self.session.connectionID) self.session._unregister_app_layer(self.session.connectionID) self.session.switch_state(State_CLOSED(self.session)) #Will never received any packet because connection unregistered from tcp layer #self.session.packet_received(packet.payload) #Can there be data in a FIN packet ? else: if packet.payload: #Acknowledge if data has been sent self.session._send_ACK(packet) #No delayed ack implemented, and should reply before 200ms RFC1122 self.session.packet_received(packet.payload) #Still forward data in case of ACK..
def connect(self, ip, port): #Ajouter support du dns """ This method try to connect to the given ip and port. If the TCP session is not CLOSED the operations are aborted. Else a local port is generated, an entry is added in iptables to preven the kernel to disturbe our connection and then a SYN packet is sent. Then the connection state is switched to SYN_SENT. The method will then loop for 20 seconds checking if the state has changed to ESTABLISHED. If not it means that a problem occured and everything is rolled back. """ if isinstance(self.state, State_CLOSED): self.localPort = random.randrange(1200, 65535) self.remoteIP = ip self.remotePort = port if not re.match(self.ipregex, ip): #Then this is a dn realip = transversal_layer_access["DNS"].nslookup(ip) if realip: self.remoteIP = realip else: raise Exception("[Errno -5] No address associated with hostname") #starting from here remoteIP contains the destination IP not DN or whatever block_outgoing_packets('tcp', None, None, self.remoteIP, port) self.connectionID = (self.remoteIP, self.remotePort, self.localIP, self.localPort) #Switch order because we are interested in receiving incoming packet so src dst is switch self.lowerLayers["default"].register_upper_layer(self.connectionID, self) self._send_SYN() self.switch_state(State_SYN_SENT(self)) #---- Wait for the connection to be established ---- exponential_backoff_values = [3*pow(2, x) for x in range(self.syn_retries)] #Precompute waiting intervals for timeout in exponential_backoff_values: instant = time.time() while (instant + timeout > time.time()): if isinstance(self.state, State_ESTABLISHED): return True self._send_SYN() #We have not received syn/ack so rollback connection unblock_outgoing_packets('tcp', None, None, self.remoteIP, port) self.lowerLayers["default"].unregister_upper_layer(self.connectionID) return False #No connection can occur if port is not open, arp request failed.. #---------------------------------------------------- else: print("Not in consistent state ("+str(self.state)+")") return False
def close(self): """ For a client will send a FIN packet and switch to FIN_WAIT1. For a server will send a FIN packet for every clients in order to unregister itself from the TCP layer """ if isinstance(self.state, State_ESTABLISHED): self._send_FIN() self.switch_state(State_FIN_WAIT_1(self)) elif isinstance(self.state, State_LISTEN): for session in self.connections: if isinstance(session.state, State_ESTABLISHED): session._send_FIN() session.switch_state(State_FIN_WAIT_1(session)) unblock_outgoing_packets('tcp', self.localIP, self.localPort, None, None) self.unregister_upper_layer(self.connectionID) self._unregister_app_layer(self.connectionID) else: print("Not in consistent state to close")
def packet_received(self, packet, **kwargs): if packet.flags == FIN: self.session.switch_state(State_FIN_WAIT_2(self.session)) #self.session.packet_received(packet.payload) #Can there be data in a FIN packet ? elif _has_flags(packet.flags, FIN + ACK): #Received FIN and Ack in the same packet self.session._send_ACK() self.session.switch_state(State_TIME_WAIT(self.session)) #?? #Directly remove the session do not switch to closed unblock_outgoing_packets('tcp', None, None, self.session.remoteIP, self.session.remotePort) self.session.unregister_upper_layer(self.session.connectionID) self.session._unregister_app_layer(self.session.connectionID) self.session.switch_state( State_CLOSED(self.session) ) #Will never received any packet because connection unregistered from tcp layer #self.session.packet_received(packet.payload) #Can there be data in a FIN packet ? else: if packet.payload: #Acknowledge if data has been sent self.session._send_ACK( packet ) #No delayed ack implemented, and should reply before 200ms RFC1122 self.session.packet_received( packet.payload) #Still forward data in case of ACK..