예제 #1
0
    def __init__(self, logger, interface, pidfile, stdout, stderr):
        """Initialises several things needed to define the daemons behaviour.

        Args:
            logger (logging.Logger): Used for logging messages.
            interface (str): The network interface which should be used. (e.g. eth0)
            pidfile (str): Path of the pidfile, used by the daemon.
            stdout (str): Path of stdout, used by the daemon.
            stderr (str): Path of stderr, used by the daemon.

        Raises:
            DaemonError: Signalises the failure of the daemon.
        """
        super(self.__class__, self).__init__(logger, interface, pidfile, stdout, stderr)
        self.redis = ApateRedis(str(self.network.network), logger)

        # Initialise threads
        self.sniffthread = SelectiveSniffThread(self.interface, self.gateway, self.mac, self.gate_mac, self.redis)
        self.sniffthread.daemon = True
        self.psthread = PubSubThread(self.redis, self.logger)
        self.psthread.daemon = True
        self.arpthread = ARPDiscoveryThread(self.gateway, str(self.network.network))
        self.arpthread.daemon = True
        self.igmpthread = IGMPDiscoveryThread(self.gateway, str(self.network.network), self.ip, self.mac)
        self.igmpthread.daemon = True
예제 #2
0
class SelectiveDaemonApp(_DaemonApp):
    """Implements the abstract class _DaemonApp and also implements the selective spoofing mode of Apate.
    The selective spoofing mode requires more resources than the holistic spoofing mode,
    e.g.: the redis-server. This mode only generates packets for existing clients (not every possible client).
    This mode is suitable for bigger networks, as the bottleneck of this mode is virtually only the host discovery.
    """

    __SLEEP = 5
    """int: Defines the time to sleep after packets are sent before they are sent anew."""

    def __init__(self, logger, interface, pidfile, stdout, stderr):
        """Initialises several things needed to define the daemons behaviour.

        Args:
            logger (logging.Logger): Used for logging messages.
            interface (str): The network interface which should be used. (e.g. eth0)
            pidfile (str): Path of the pidfile, used by the daemon.
            stdout (str): Path of stdout, used by the daemon.
            stderr (str): Path of stderr, used by the daemon.

        Raises:
            DaemonError: Signalises the failure of the daemon.
        """
        super(self.__class__, self).__init__(logger, interface, pidfile, stdout, stderr)
        self.redis = ApateRedis(str(self.network.network), logger)

        # Initialise threads
        self.sniffthread = SelectiveSniffThread(self.interface, self.gateway, self.mac, self.gate_mac, self.redis)
        self.sniffthread.daemon = True
        self.psthread = PubSubThread(self.redis, self.logger)
        self.psthread.daemon = True
        self.arpthread = ARPDiscoveryThread(self.gateway, str(self.network.network))
        self.arpthread.daemon = True
        self.igmpthread = IGMPDiscoveryThread(self.gateway, str(self.network.network), self.ip, self.mac)
        self.igmpthread.daemon = True

    def _return_to_normal(self):
        """This method is called when the daemon is stopping.
        First, sends a GARP broadcast request to all clients to tell them the real gateway.
        Then ARP replies for existing clients are sent to the gateway.
        """
        # spoof clients with GARP boradcast request
        sendp(
            Ether(dst=ETHER_BROADCAST) / ARP(op=1, psrc=self.gateway, pdst=self.gateway, hwdst=ETHER_BROADCAST,
                                             hwsrc=self.gate_mac))

        # generate ARP reply packet for every existing client and spoof the gateway
        packets = [Ether(dst=self.gate_mac) / ARP(op=2, psrc=dev[0], pdst=self.gateway, hwsrc=dev[1]) for dev in self.redis.get_devices_values(filter_values=True)]
        sendp(packets)

    def exit(self, signal_number, stack_frame):
        """This method is called from the python-daemon when the daemon is stopping.
        Threads are stopped and clients are despoofed via _return_to_normal().
        """
        self._return_to_normal()
        raise SystemExit()

    def run(self):
        """Starts multiple threads sends out packets to spoof
        all existing clients on the network and the gateway. This packets are sent every __SLEEP seconds.
        The existing clients (device entries) are read from the redis database.

        Threads:
            A SniffThread, which sniffs for incoming ARP packets and adds new devices to the redis db.
            Two HostDiscoveryThread, which are searching for existing devices on the network.
            A PubSubThread, which is listening for redis expiry messages.

        Note:
            First, ARP replies to spoof the gateway entry of existing clients arp cache are generated.
            ARP relpies to spoof the entries of the gateway are generated next.
            Unlike the holistic mode only packets for existing clients are generated.

        """
        self.sniffthread.start()
        self.arpthread.start()
        self.psthread.start()
        self.igmpthread.start()

        # lamda expression to generate arp replies to spoof the clients
        exp1 = lambda dev: Ether(dst=dev[1]) / ARP(op=2, psrc=self.gateway, pdst=dev[0], hwdst=dev[1])

        # lamda expression to generate arp replies to spoof the gateway
        exp2 = lambda dev: Ether(dst=self.gate_mac) / ARP(op=2, psrc=dev[0], pdst=self.gateway, hwdst=self.gate_mac)

        while True:
            # generates packets for existing clients
            # due to the labda expressions p1 and p2 this list comprehension, each iteration generates 2 packets
            # one to spoof the client and one to spoof the gateway
            packets = [p(dev) for dev in self.redis.get_devices_values(filter_values=True) for p in (exp1, exp2)]

            sendp(packets)
            time.sleep(self.__SLEEP)