예제 #1
0
파일: TapLoop.py 프로젝트: grwl/pscan
class TapLoop:
	'''
	This class creates a pair of interconnected TAP interfaces.
	If address and netmask are provided, they get assigned to the "remote" interface.
	The users are supposed to call get_iface() method to obtain the name of the "local" interface.
	Then the users are expected to use raw sockets to send/receive traffic on that local interface,
	possibly to interact with the remote end.
	'''
	def __init__(self, local_address = None, remote_address = None, netmask = None):
		self.t1 = TapDevice(mode = IFF_TAP)
		self.t2 = TapDevice(mode = IFF_TAP)

		if local_address != None and netmask != None:
			self.t1.ifconfig(address = local_address, netmask = netmask)

		if remote_address != None and netmask != None:
			self.t2.ifconfig(address = remote_address, netmask = netmask)

		self.t1.up()
		self.t2.up()

		self.pump1 = Pump(self.t1, self.t2)
		self.pump2 = Pump(self.t2, self.t1)

		logger.debug("Allocated TAP interfaces %s/%s" % (self.t1.name, self.t2.name))

	def start(self):
		self.pump1.start()
		self.pump2.start()
		logger.debug("Started pump threads")

	def get_iface(self):
		return self.t1.name
예제 #2
0
class LoadbalancerControl(asyncore.file_dispatcher):
    shutdown = False    # Loadbalancers shouldn't reconnect
    rr = 0              # RoundRobin iterator counter

    def __init__(self, options={}):
        self.secret = options.get('secret','')
        self.port = options.get('port',11111)
        self.buffer = []
        self.loadbalancer_pool = []

        _tap = options.get('tap', True)
        _name = options.get('name', '')
        self.dev = TapDevice(tap=_tap, name=_name)

        asyncore.file_dispatcher.__init__(self, self.dev.getFD())

        self.dev.up()
        if options.get('tunnel_address', False):
            self.dev.ifconfig(address=options.get('tunnel_address'))

        logging.debug('Interface ready')

    def eth_addr (self, a) :
        b = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" % (ord(a[0]) , ord(a[1]) , ord(a[2]), ord(a[3]), ord(a[4]) , ord(a[5]))
        return b

    def validate(self, data):
        eth_length = 14
         
        eth_header = data[:eth_length]
        eth = struct.unpack('!6s6sH' , eth_header)
        eth_protocol = socket.ntohs(eth[2])
#        print 'Destination MAC : ' + self.eth_addr(data[0:6]) + ' Source MAC : ' + self.eth_addr(data[6:12]) + ' Protocol : ' + str(eth_protocol)

        ip_header = data[eth_length:20+eth_length]
        iph = struct.unpack('!BBHHHBBH4s4s' , ip_header)
        version_ihl = iph[0]
        ihl = version_ihl & 0xF

        iph_length = ihl * 4
        protocol = iph[6]
        s_addr = socket.inet_ntoa(iph[8])
        d_addr = socket.inet_ntoa(iph[9])

#        udp_header = data[iph_length+eth_length:iph_length+20+eth_length]
#        udph = struct.unpack('!HHLLBBHHH' , udp_header)
#        print "[{}] - {}:{} -> {}:{}".format(protocol, s_addr,udph[0], d_addr,udph[1])

    def writable(self):
        return len(self.buffer) > 0

    def handle_write(self):
        """ Write local buffer to interface """
        try:
            packet = self.buffer.pop()
            logging.debug('Writing {}byte packet to device'.format(len(packet)))
            self.dev.write(packet)
        except IndexError:
            pass
        except OSError as e:
            if e.errno == 22:
                # Invalid packet
                logging.debug('Failed to write invalid packet "{}"'.format(packet))
            else:
                logging.exception('Writing "{}" to device caused exception: {}'.format(packet, e.strerror))
        except Exception as e:
            logging.exception('Writing "{}" to device caused exception: {}'.format(packet, e.strerror))

    def write(self, packet):
        """ Forward data from loadbalancers to local buffer """
        if packet:
#            self.validate(packet)
            self.buffer.append(packet)

    def handle_read_event(self):
        """ Forward received packets to loadbalancers """
        packet = self.dev.read()
        self.balance_data_round_robin(packet)

    def balance_data_round_robin(self, packet):
        """ Use Round Robin to distribute each packet via revolving loadbalancers """
        if len(self.loadbalancer_pool) == 0:
            return
        
#        logging.debug('Sending {}byte packet via {}'.format(len(packet), repr(self.loadbalancer_pool[self.rr])))
        self.loadbalancer_pool[self.rr].send(packet)
        self.rr = self.rr+1 if self.rr < len(self.loadbalancer_pool)-1 else 0

    def quit(self):
        """ Gracefully close all loadbalancers and self """
        self.shutdown = True
        logging.debug('Closing loadbalancers...')
        # Loadbalancer modifies the pool in close, so make a static list
        for s in list(self.loadbalancer_pool):
            s.handle_close()

        if self.loadbalancer_pool:
            logging.debug('Waiting for loadbalancers to close...')
            for i in range(5):
                if len(self.loadbalancer_pool) == 0:
                    break
                time.sleep(1)
            else:
                for s in self.loadbalancer_pool:
                    s.close()
                    del s

        logging.debug('Closing self...')
        self.dev.close()