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 == SYN: #Don't check if the dstport is the same because it has been check in tcp #--- Check we have not exceeded the number of connections count = 0 for sess in self.session.connections: if not isinstance(sess.state, State_CLOSED): count += 1 if count >= self.session.nbconntoaccept: self.session.sendRST(packet, **kwargs) return #-------------------------------------------------- session = TCPSession(self.session.interface) session.seqNo = packet.ack session.ackNo = packet.seq + 1 session.localPort = packet.dport session.remoteIP = kwargs["IP"]["src"] session.remotePort = packet.sport block_outgoing_packets('tcp', None, None, session.remoteIP, session.remotePort) connID = (session.remoteIP, session.remotePort, session.localIP, session.localPort) session.connectionID = connID self.session.lowerLayers["default"].register_layer_full( connID, session) if self.session.newinstance: newapp = self.session.app.__new__(type(self.session.app)) newapp.__init__() session.register_layer(newapp) session.upperLayers["Raw"].hook_incoming( packet, **kwargs ) #Cause if a new instance is created the SYN packet is received by the socket server in listen, and not the application itself so call hook again here else: session.register_upper_layer("Raw", self.session.app) self.session.app.register_lower_layer(session.connectionID, session) #session.register_layer_full("Raw", self.session.app) session._send_SYNACK(packet) session.switch_state(State_SYN_RCVD(session)) self.session.connections.append(session) elif _has_flags(packet.flags, RST): #(TCP/IP illustrated Volume 2 p.999) pass #Ignore the packet elif _has_flags(packet.flags, ACK): print 'state_listen2' self.session.sendRST(packet, **kwargs) else: pass #What should we do ?
def bind(self, port, app=None, newinstance=False): """ The bind method is quite ligthweight. It justs register itself to the TCP protocol as a handler and an entry is added to iptables to prevent the Hosting host to reply with RST. Note app and newinstance define on which TCPApplication client connections should be redirected and if the TCPApplication should be forked for every client or not. """ self.app = app if app else TCPApplication() self.newinstance = newinstance self.localPort = port block_outgoing_packets("tcp", self.localIP, self.localPort, None, None) self.connectionID = (self.localIP, self.localPort) self.lowerLayers['default'].register_upper_layer(self.connectionID, self)
def bind(self, port, app=None, newinstance=False): """ The bind method is quite ligthweight. It justs register itself to the TCP protocol as a handler and an entry is added to iptables to prevent the Hosting host to reply with RST. Note app and newinstance define on which TCPApplication client connections should be redirected and if the TCPApplication should be forked for every client or not. """ self.app = app if app else TCPApplication() self.newinstance = newinstance self.localPort = port block_outgoing_packets("tcp", self.localIP, self.localPort, None, None) self.connectionID = (self.localIP, self.localPort) self.lowerLayers['default'].register_upper_layer( self.connectionID, self)
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 == SYN: #Don't check if the dstport is the same because it has been check in tcp #--- Check we have not exceeded the number of connections count = 0 for sess in self.session.connections: if not isinstance(sess.state, State_CLOSED): count += 1 if count >= self.session.nbconntoaccept: self.session.sendRST(packet, **kwargs) return #-------------------------------------------------- session = TCPSession(self.session.interface) session.seqNo = packet.ack session.ackNo = packet.seq + 1 session.localPort = packet.dport session.remoteIP = kwargs["IP"]["src"] session.remotePort = packet.sport block_outgoing_packets('tcp', None, None, session.remoteIP, session.remotePort) connID = (session.remoteIP, session.remotePort, session.localIP, session.localPort) session.connectionID = connID self.session.lowerLayers["default"].register_layer_full(connID, session) if self.session.newinstance: newapp = self.session.app.__new__(type(self.session.app)) newapp.__init__() session.register_layer(newapp) session.upperLayers["Raw"].hook_incoming(packet, **kwargs) #Cause if a new instance is created the SYN packet is received by the socket server in listen, and not the application itself so call hook again here else: session.register_upper_layer("Raw", self.session.app) self.session.app.register_lower_layer(session.connectionID, session) #session.register_layer_full("Raw", self.session.app) session._send_SYNACK(packet) session.switch_state(State_SYN_RCVD(session)) self.session.connections.append(session) elif _has_flags(packet.flags, RST): #(TCP/IP illustrated Volume 2 p.999) pass #Ignore the packet elif _has_flags(packet.flags, ACK): self.session.sendRST(packet, **kwargs) else: pass #What should we do ?