Example #1
0
    def check_layers(self, packet):
        """
        Hand over packets to the layer controller or trackers

        :param packet: ipv4 / ipv6 packet (scapy), packet can be modified in this method
        :return: forward (should it be forwarded to the network stack)
        """
        forward = True
        #check every controller or translator
        for (id, controller) in sorted(self._controller.items()):
            if isinstance(controller, ILayerController):
                # check if layer for controller exists
                layer_types = controller.layers()
                for layer in layer_types:
                    if packet.haslayer(layer):
                        InternalLogger.get().debug("Forwarding to controller" + str(type(controller)))
                        #original packet, translators can modify
                        forward_controller = controller.process_packet(packet)
                        forward = forward and forward_controller
                        break # Dont send to controller twice
            elif isinstance(controller, IConnectionTracker):
                #Copy Packet, dont allow to change it
                #Track in new thead (no realtime changes required)
                packet_copy = copy.deepcopy(packet)
                InternalLogger.get().debug("Forwarding to tracker" + str(type(controller)))
                self._executor.submit(self.forward_to_tracker, controller, packet_copy, self._io)
        return forward
Example #2
0
    def check_buffer(self, packet):
        """
        Check if a mapping for the connection exisits in the connection tacker buffer
        :param packet:
        :return:
        """
        tracked_ip = None
        if packet.haslayer(TCP):
            tcp = packet[TCP]
            port = 0
            if self._io == IO.INPUT:
                port = tcp.dport
            else:
                port = tcp.sport
            # check if this connection is allowed to continue based on connection tracking
            result = self._nas_tracker.check_buffer(packet, self._io)

            if result is not None:
                (ip, enforced) = result
                if self._dyn_port_priority.allow_continue(port) or enforced:
                    tracked_ip = ip
                else:
                    InternalLogger.get().debug(
                        "DynPort Priority doesnt allow the connection to continue (dest rPort = "
                        + str(port) + ") and it has not been enforced")
        return tracked_ip
    def clean_buffer(self):
        """

        """
        # Cleanup
        while len(self._connection_buffer) > self._max_buffer:
            # remove first element(s)
            InternalLogger.get().debug("Removing element from buffer")
            with self._lock.gen_wlock():
                self._connection_buffer.popitem(last=True)
Example #4
0
    def add_hf_mapping(self, hf_mapping):
        """
        called by REST endpoint

        add high frequency mapping from other gateway to internal mapping

        :param hf_mapping: high frequency mapping
        """
        InternalLogger.get().debug("Adding addresses")
        InternalLogger.get().debug(hf_mapping)
        self._hf_mapping_other.update(hf_mapping)
        # Recalculate total mapping (merge) and send
        self.send_new_mapping()
Example #5
0
    def virtual_port_to_rport(self, v_port, client_ip, client_key):
        """

        :param v_port: Int, Virtual Port
        :param client_ip: String, Client IP Address
        :param client_key: String, Client PreShared Key
        :return: Real Port, Int
        """
        t = self.get_T()
        h = self.get_hash(t, client_key, client_ip)
        r_port = h ^ v_port
        InternalLogger.get().debug("RPAH rPort =" + str(r_port))
        return r_port
Example #6
0
    def real_port_to_vport(self, r_port, client_ip, client_key):
        """

        :param r_port: Int, Real Port
        :param client_ip: String, Client IP Address
        :param client_key: String, Client PreShared Key
        :return: Virtual Port, Int
        """
        t = self.get_T()
        h = self.get_hash(t, client_key, client_ip)
        v_port = h ^ r_port
        InternalLogger.get().debug("RPAH vPort =" + str(v_port))
        return v_port
Example #7
0
    def run(self):
        """
            Run this class in new thread and start packet receiver
        """
        InternalLogger.get().debug("Starting IP-Controller, queue_num=" + str(self._queue_num))
        try:
            q = self.conn.bind(self._queue_num)
            q.set_mode(fnfqueue.MAX_PAYLOAD, fnfqueue.COPY_PACKET)
        except PermissionError:
            InternalLogger.get().error("Access denied; Do I have root rights or the needed capabilities?")
            sys.exit(-1)

        while True:
            try:
                for packet in self.conn:
                    self.receive(packet)
            except fnfqueue.BufferOverflowException:
                InternalLogger.get().error("Buffer Error")
                '''
                In case packets arrive too
                fast at the kernel side, the socket buffer overflows and a
                BufferOverflowException is raised.
                '''
                self.conn.reset() # try to solve Overflow
                pass
            except Exception as e:
                InternalLogger.get().critical("Error: " + str(e), exc_info=True)
Example #8
0
    def revoke_hf_mapping(self, hf_mapping):
        """
        called by REST endpoint

        revoke parts of the high frequency mapping from other gateways

        :param hf_mapping: revoked high frequency mapping
        """

        InternalLogger.get().debug("Revoking addresses")
        InternalLogger.get().debug(hf_mapping)
        #delete revoked mappings
        for v_ip, r_ip in hf_mapping.items():
            if self._hf_mapping_other.get(v_ip) is not None:
                del self._hf_mapping_other[v_ip]
        # Recalculate total mapping (merge) and send
        self.send_new_mapping()
Example #9
0
 def send_new_mapping(self):
     """
     Merge external (other gateways) and internal mappings
     send new mapping to the receivers = translators (trackers/controllers) internally
     send new mapping to other gatways (defined in nas/receiver) if necessary
     """
     total_mapping = {}
     #Internal mapping
     if self._hf_mapping is not None:
         total_mapping.update(self._hf_mapping)
     #external mapping
     if self._hf_mapping_other is not None:
         total_mapping.update(self._hf_mapping_other)
     #send new mapping to translators
     for translator in self._translators:
         #POSSIBLE: total_mapping just for DNS
         translator.set_mapping(total_mapping)
     InternalLogger.get().debug("Total Mapping")
     InternalLogger.get().debug(total_mapping)
     #send new mapping to other gateways
     self._executor.submit(self.send_all_rest)
    def add_connection(self, sourceIP, sourcePort, dest_vIP, dest_rPort,
                       dest_rIP, enforce):
        """
        Add connection information for connection which should be generated in other components

        :param sourcePort: Source Port
        :param sourceIP: Source IP-Address
        :param dest_rPort: Destination virtual Port
        :param dest_vIP:  Destination virtual IP-Address
        :param dest_rIP: Destination real IP-Address
        :param enforce: Tell other modules that this connection should be kept alive (even if other security measures prohibit it)
        """
        with self._lock.gen_wlock():
            packet_data = (sourceIP, sourcePort, dest_vIP, dest_rPort)
            InternalLogger.get().debug(
                "Added external connection to tracker: " + str(packet_data) +
                ": " + dest_rIP)
            self._connection_buffer[packet_data] = (False, dest_rIP, enforce)
            # (TCP Ident) : (Fin tracked, mapped dst)
            self._connection_buffer.move_to_end(
                packet_data, last=False)  # move to the beginning
Example #11
0
    def get_hash(self, t, key, client_ip):
        """

        :param t:  t = T = Time Interval Value
        :param key: PSK
        :param client_ip: IP of the Client
        :return: Hash
        """

        #Search in Buffer first
        InternalLogger.get().debug("Searching for hash in buffer")
        hash_int = self._hash_buffer.get((t, key, client_ip))
        if hash_int is not None:
            InternalLogger.get().debug("Found hash in buffer")
            self._hash_buffer.move_to_end((t, key, client_ip), last=False)
            return hash_int

        # Generate
        InternalLogger.get().debug("Trying to generate hash")
        h = hashlib.blake2b(digest_size=2)  # optimized for 64 bit
        h.update(bytes(t))
        h.update(key.encode())
        h.update(client_ip.encode())
        hash_result = h.digest()
        hash_int = int.from_bytes(hash_result, byteorder='big', signed=False)

        # Save to buffer
        self._hash_buffer[(t, key, client_ip)] = hash_int
        self._hash_buffer.move_to_end((t, key, client_ip),
                                      last=False)  # move to the beginning
        # Cleanup
        while (len(self._hash_buffer) > self._max_buffer):
            #remove first element(s)
            self._hash_buffer.popitem(last=True)
        return hash_int
    def block_hf_shuffling(self):
        """
        Check if HF Shuffling should be blocked

        :returns Boolean
        """
        if self._continue_all:
            #Dont need to block
            return False

        active_ports = self._nas_connection_tracker.get_active_ports()
        block_value = 0
        for port in active_ports:
            priority = self._priority_list.get(str(port))
            if priority is None:
                InternalLogger.get().debug("No Priority found for port " +
                                           str(port))
            else:
                priority_block_value = self._priority_definition.get(priority)
                if priority_block_value is None:
                    InternalLogger.get().error(
                        "No Priority definition found for " + str(priority))
                else:
                    if priority_block_value > block_value:
                        block_value = priority_block_value
        InternalLogger.get().debug("Highest Priority Block Value: " +
                                   str(block_value))
        block = self._shuffling_blocked_count < block_value
        if block:
            InternalLogger.get().debug("DynPort Blocking (count = " +
                                       str(self._shuffling_blocked_count) +
                                       ")")
            self._shuffling_blocked_count = self._shuffling_blocked_count + 1
        else:
            InternalLogger.get().debug("DynPort NOT Blocking (count = " +
                                       str(self._shuffling_blocked_count) +
                                       ")")
            self._shuffling_blocked_count = 0
        return block
Example #13
0
    def process_packet(self, packet):
        """

        :param packet: IPv4 / IPv6 packet
        :return: forward?
        """
        InternalLogger.get().debug("DNS Controller processing packet...")
        # .show() = all layer informations
        #Check if it has the DNSRR Layer
        if packet.haslayer(DNSRR):
            #Extract Data

            #resource IP
            rdata = packet[DNSRR].rdata
            #resource Name (Domain)
            rrname = packet[DNSRR].rrname
            dns_type = packet[DNSRR].type
            if self._mapping is not None:
                new_ip = self._mapping.get(rdata)
                if new_ip is not None:
                    #vIP found in Mapping
                    InternalLogger.get().debug(
                        "DNS Response IP Replaced for " + str(rrname) +
                        "; new = " + str(new_ip) + "; old = " + str(rdata))
                    #create new response and add it to the existing packet
                    dns_response = DNSRR(rrname=rrname,
                                         rdata=new_ip,
                                         type=dns_type,
                                         ttl=self._ttl)
                    packet[DNS].an = dns_response
                    #change answer count
                    packet[DNS].ancount = 1
            else:
                InternalLogger.get().error("DNS Mapping is None")
        else:
            InternalLogger.get().error("No DNSRR Layer (Translator)")
        return True
Example #14
0
 def send_all_rest(self):
     """
     Send the High Frequency mapping (total) to Receivers (REST endpoint of other gateways) if necessary
     """
     try:
         for url in self._receiver:
             #Send mapping to url of receiver
             InternalLogger.get().debug("Sending Mapping to: " + url)
             #Create structure
             json_structure = {}
             #add new mapping
             json_structure["hf_added"] = self._hf_mapping
             #revoke old mapping
             json_structure["hf_revoked"] = self._hf_mapping_old
             json_mapping = json.dumps(json_structure)
             headers = {"Content-Type": "application/json"}
             #Send via HTTP
             r = requests.put(url, data=json_mapping, headers=headers)
             InternalLogger.get().debug("Status: " + str(r.status_code))
     except Exception as e:
         InternalLogger.get().error("Error: " + str(e), exc_info=True)
Example #15
0
    def process_packet(self, packet):
        """
        Forward the packet to the translator if necessary

        :param packet: IPv4/IPv6 Packet with TCP or UDP Payload
        :return: forward?
        """
        #check if source or dst ip is in ph_subnet_server list
        is_not_in_sever_subnet = False
        for subnet in self._ph_subnet_server:
            netw = IPNetwork(subnet)
            if not (packet.dst in netw or packet.src in netw):
                is_not_in_sever_subnet = True
        if is_not_in_sever_subnet:
            InternalLogger.get().debug(
                "PH: Forwarding the incoming packet, not a connection to a MTD Host"
            )

        #check if source or dst ip is in whitelist (for incoming and leaving packets)
        is_whitelist = False
        for whitelist_address in self._whitelist:
            netw = IPNetwork(whitelist_address)
            if packet.dst in netw or packet.src in netw:
                is_whitelist = True
                break

        if is_whitelist:
            InternalLogger.get().debug(
                "PH: Forwarding the incoming packet, no MTD Host and in whitelist"
            )
        #check if destination is this host (local address)
        elif packet.dst in self._network_helper.local_addresses():
            InternalLogger.get().debug(
                "PH: Accepting the incoming packet, destination = local address"
            )
        else:
            #translate ports
            return self._translate(packet)
        return True
Example #16
0
    def _translate(self, packet):
        """
        Translate ports

        :param packet: IPv4/IPv6 Packet with TCP or UDP Payload
        :return: forward?
        """
        InternalLogger.get().debug("Trying to translate port...")
        #check if packet has TCP or UDP payload and extract it
        tcp_or_udp = None
        if packet.haslayer(TCP):
            tcp_or_udp = packet[TCP]
        if packet.haslayer(UDP):
            tcp_or_udp = packet[UDP]
        if tcp_or_udp is None:
            InternalLogger.get().error("ERROR: No TCP or UDP Layer found")
            return True  #Internal Error? Forward Anyways

        new_port = None
        #Translate incoming packets
        if self._io == IO.INPUT:
            if self._client:
                #Gateway is part of the client network
                ip = packet.dst
                key = self._keymap.get(ip)
                if key is None:
                    # No key, drop packet
                    InternalLogger.get().debug("No key for " + ip)
                    return False
                old_port = tcp_or_udp.sport
                new_port = self._ph_function.virtual_port_to_rport(
                    old_port, ip, key)
                tcp_or_udp.sport = new_port
            else:
                # Gateway is part of the host network
                ip = packet.src
                key = self._keymap.get(ip)
                if key is None:
                    # No key, drop packet
                    InternalLogger.get().debug("No key for " + ip)
                    return False
                old_port = tcp_or_udp.dport
                new_port = self._ph_function.virtual_port_to_rport(
                    old_port, ip, key)
                tcp_or_udp.dport = new_port
        else:
            #Translate leaving packets
            if self._client:
                # Gateway is part of the client network
                ip = packet.src
                key = self._keymap.get(ip)
                if key is None:
                    # No key, drop packet
                    InternalLogger.get().debug("No key for " + ip)
                    return False
                old_port = tcp_or_udp.dport
                new_port = self._ph_function.real_port_to_vport(
                    old_port, ip, key)
                tcp_or_udp.dport = new_port
            else:
                # Gateway is part of the host network
                ip = packet.dst
                key = self._keymap.get(ip)
                if key is None:
                    InternalLogger.get().debug("No key for " + ip)
                    #No key, drop packet
                    return False
                old_port = tcp_or_udp.sport
                new_port = self._ph_function.real_port_to_vport(
                    old_port, ip, key)
                tcp_or_udp.sport = new_port

        if new_port is None:
            InternalLogger.get().error("Error no rPort found")
            return
        InternalLogger.get().debug("Old Port = " + str(old_port))
        InternalLogger.get().debug("New Port = " + str(new_port))
        return True
Example #17
0
    def put(self):
        """
        HTTP Put Request
        """
        try:
            InternalLogger.get().debug("Received mapping")
            #Check for json errors
            data = request.json
            if data is None:
                InternalLogger.get().debug("Error: No JSON Data")
                return
            if type(data) is not dict:
                InternalLogger.get().debug("Error: No Dictionary")
                return
            #Receive LF Data
            lf = data.get("lf")
            if lf is not None:
                InternalLogger.get().debug("-> lf mapping received")
                for controller in self._subnet_controller:
                    controller.set_lf_mapping(lf)
            #Received new HF Data
            hf_added = data.get("hf_added")
            if hf_added is not None:
                InternalLogger.get().debug("-> hf_added mapping received")
                for controller in self._subnet_controller:
                    controller.add_hf_mapping(hf_added)
            #Receive revoked HF Data
            hf_revoked = data.get("hf_revoked")
            if hf_revoked is not None:
                InternalLogger.get().debug("-> hf_revoked mapping received")
                for controller in self._subnet_controller:
                    controller.revoke_hf_mapping(hf_revoked)
            lf_subnet = data.get("virtual_subnets")
            if lf_subnet is not None:
                for controller in self._subnet_controller:
                    controller.set_hf_subnet(lf_subnet)

        except Exception as e:
            InternalLogger.get().debug("Error: " + str(e))
            InternalLogger.get().debug(traceback.format_exc())
    def check_buffer(self, packet, io):
        """
        Search in NAS Track Buffer

        :param packet: IPv4 / IPv6 Packet
        :param io: Input/Output
        :return: (rIP or None if no rIP has been found, enforced)
        """
        InternalLogger.get().debug("Searching for connection in buffer")
        if packet.haslayer(TCP):
            tcp = packet[TCP]
            if len(self._connection_buffer) > 0:
                #Check for incoming packets
                if io == IO.INPUT:
                    ##WARNING: Use PH function to translate PORTS

                    packet_data = (packet.src, tcp.sport, packet.dst,
                                   tcp.dport)
                    InternalLogger.get().debug("Searching in Buffer for: " +
                                               str(packet_data))
                    with self._lock.gen_rlock():
                        result = self._connection_buffer.get(packet_data)
                    if result is not None:
                        (fin, ip, enforced) = result
                        InternalLogger.get().debug("Found mapping in buffer")
                        with self._lock.gen_wlock():
                            self._connection_buffer.move_to_end(packet_data,
                                                                last=False)
                        return (ip, enforced)
                    else:
                        InternalLogger.get().debug("Connection not found")
                else:
                    #Check for leaving packet
                    InternalLogger.get().debug("Searching in Buffer for: " +
                                               str(packet.src))
                    result_dst = None
                    result_packet_data = None
                    with self._lock.gen_rlock():
                        #check connections in order
                        #old connections with similar tuple will not be used because of the order
                        for packet_data, (
                                fin, r_ip,
                                enforced) in self._connection_buffer.items():
                            (src, sport, dst, dport) = packet_data
                            if src == packet.dst and dport == tcp.sport and sport == tcp.dport and r_ip == packet.src:
                                InternalLogger.get().debug(
                                    "Found mapping in buffer (reverse)")
                                result_packet_data = packet_data
                                result_dst = (dst, enforced)
                                break
                    if result_packet_data is not None:
                        with self._lock.gen_wlock():
                            #Check again if it has been deleted (protect against race conditions)
                            if self._connection_buffer.get(
                                    packet_data) is not None:
                                self._connection_buffer.move_to_end(
                                    result_packet_data, last=False)
                    if result_dst is None:
                        InternalLogger.get().debug(
                            "Connection not found (reverse)")
                    return result_dst
        return None
Example #19
0
 def recalculate_mapping(self):
     """
     Recualculate mapping (rIP addresses)
     """
     InternalLogger.get().info("--HF Controller recalculating mapping")
     new_mapping = {}
     if self._lf_mapping is not None:
         # Calculate new vIP for every rIP (ip) and the given subnet
         for ip, subnet in self._lf_mapping.items():
             InternalLogger.get().debug("-Checking " + ip + ", subnet " +
                                        subnet)
             #create network of the subnet
             network = IPNetwork(subnet)
             #get network size
             total_count = network.size
             #select random vIP
             rand = secrets.randbelow(total_count)
             InternalLogger.get().debug(
                 str(total_count) + " addresses possible")
             v_ip = str(network[rand])
             InternalLogger.get().debug("New IP: " + str(v_ip))
             #Set mapping
             new_mapping[v_ip] = ip
     else:
         InternalLogger.get().debug("Error: No LF Mapping")
     InternalLogger.get().debug("--HF Controller finished")
     InternalLogger.get().debug(new_mapping)
     #save old mapping and set new mapping
     self._hf_mapping_old = self._hf_mapping
     self._hf_mapping = new_mapping
     #send new mapping to other gatways (defined in nas/receiver) if necessary
     self.send_new_mapping()
Example #20
0
    def run(self):
        """
        Run HFController in new thread
        Recalculate mappings (rIP addresses) regulary in a time interval (hopping period)
        """
        try:
            while True:
                InternalLogger.get().debug("HF Controller starting")
                InternalLogger.get().debug(
                    "--------------------------------------------------------------"
                )
                if self._dynamic_port_priority.block_hf_shuffling():
                    InternalLogger.get().debug(
                        "HF Recalculate Process blocked by DynPortPriority")
                else:
                    self.recalculate_mapping()

                InternalLogger.get().debug("HF Controller stopping")
                InternalLogger.get().debug(
                    "--------------------------------------------------------------"
                )
                time.sleep(self._hopping_period)
        except KeyboardInterrupt as e:
            InternalLogger.get().debug(e)
        except Exception as e:
            InternalLogger.get().error("Error: " + str(e), exc_info=True)
    def track_connection(self, packet, io):
        """

        :param packet: IPv4 / IPv6 Packet
        :param io: Input/Output
        """
        InternalLogger.get().debug("Trying to track connection")
        '''
        called before (incoming) and after (outgoing) ph translations
        tracks connections with virtual ip addresses and real ports
        '''
        if packet.haslayer(TCP):
            tcp = packet[TCP]
            packet_data = None
            if io == IO.INPUT:
                packet_data = (packet.src, tcp.sport, packet.dst, tcp.dport)
            else:
                packet_data = (packet.dst, tcp.dport, packet.src, tcp.sport)
            InternalLogger.get().debug("Tracking packet: " + str(packet_data))
            if tcp.flags.S:
                #SYN has been received, Check if it a new connection
                result = None
                with self._lock.gen_rlock():
                    result = self._connection_buffer.get(packet_data)
                if result is None:
                    InternalLogger.get().debug(
                        "SYN received for the first time, trying to add mapping"
                    )
                    new_ip = self._mapping.get(packet.dst)
                    if new_ip is not None:
                        with self._lock.gen_wlock():
                            self._connection_buffer[packet_data] = (False,
                                                                    new_ip,
                                                                    False)
                            # (TCP Ident) : (Fin tracked, mapped dst)
                            self._connection_buffer.move_to_end(
                                packet_data,
                                last=False)  # move to the beginning
                            self.clean_buffer()
                    else:
                        InternalLogger.get().debug(
                            "No new rIP for connection in tracker")
            elif tcp.flags.F:
                #CFIN has been received, connection will close and receive one more ACK
                result = None
                with self._lock.gen_rlock():
                    result = self._connection_buffer.get(packet_data)
                if result is not None:
                    (fin, ip, enforced) = result
                    InternalLogger.get().debug(
                        "FIN received for the first time, FIN = True")
                    with self._lock.gen_wlock():
                        self._connection_buffer[packet_data] = (True, ip,
                                                                enforced)
            elif tcp.flags.A:
                #Check if last ACK (after FIN) has been received
                result = None
                with self._lock.gen_rlock():
                    result = self._connection_buffer.get(packet_data)
                if result is not None:
                    (fin, ip, enforced) = result
                    if fin:
                        InternalLogger.get().debug(
                            "ACK received (Last Ack), deleting mapping")
                        with self._lock.gen_wlock():
                            self._connection_buffer.pop(packet_data)
Example #22
0
    def process_packet(self, packet):
        """

        :param packet: IPv4 /Ipv6 Packet
        :return: Forward?
        """
        #manipulate incoming packet
        if self._io == IO.INPUT:
            if self._mapping is not None:
                new_ip = self._mapping.get(packet.dst)
                #vIP found in Mapping
                if new_ip is not None:
                    packet.dst = new_ip
                    InternalLogger.get().debug("DST changed to " + new_ip +
                                               "(from mapping)")
                else:
                    #no vIP found in mapping
                    is_whitelist = False
                    #search in whitelist
                    for whitelist_address in self._whitelist:
                        if packet.dst in IPNetwork(whitelist_address):
                            is_whitelist = True
                            break
                    if is_whitelist:
                        InternalLogger.get().debug(
                            "IP-NAS: Forwarding the incoming packet, "
                            "whitelist")
                        return True
                    #search in local addresses (should it be forwarded to this host internally?)
                    elif packet.dst in self._network_helper.local_addresses():
                        InternalLogger.get().debug(
                            "IP-NAS: Accepting the incoming packet, destination = local address"
                        )
                        return True

                    #search for vIP in Connection Tracker
                    InternalLogger.get().debug(
                        "No mapping, searching tracker buffer")
                    new_ip_tracked = None
                    if self._track:
                        new_ip_tracked = self.check_buffer(packet)
                    else:
                        InternalLogger.get().debug(
                            "WARNING: Tried to reach MT Area, DROPPED")
                    if new_ip_tracked is not None:
                        #vIP found
                        packet.dst = new_ip_tracked
                    else:
                        #Send to honeypot?
                        if self._honeypot and packet.haslayer(TCP):
                            vsubnet = False
                            #check if destination is part of the virtual subnet
                            if self._virtual_subnets is not None:
                                for subnet in self._virtual_subnets:
                                    if packet.dst in IPNetwork(subnet):
                                        vsubnet = True
                                        break
                            else:
                                InternalLogger.get().error(
                                    "No virtual subnets")
                            if vsubnet:
                                #dst is in vSubnet, set honeypot
                                new_ip_honeypot = None
                                if IPAddress(packet.dst).version == 4:
                                    new_ip_honeypot = self._honey_v4
                                else:
                                    new_ip_honeypot = self._honey_v6
                                if new_ip_honeypot is not None:
                                    #add to connection tracking:
                                    tcp = packet[TCP]
                                    self._nas_tracker.add_connection(
                                        packet.src, tcp.sport, packet.dst,
                                        tcp.dport, new_ip_honeypot, True)
                                    packet.dst = new_ip_honeypot

                                    InternalLogger.get().debug(
                                        "WARNING: Tried to reach MT Area, forwarded to HONEYPOT ("
                                        + new_ip_honeypot + ")")
                                    return True
                                else:
                                    InternalLogger.get().error(
                                        "No HoneyPot Address")
                                    return False
                            else:
                                InternalLogger.get().debug(
                                    "WARNING: Tried to reach MT Area, DROPPED (Not in Virtual Subnet, Honeypot not used)"
                                )
                        else:
                            #vIP not found
                            InternalLogger.get().debug(
                                "WARNING: Tried to reach MT Area, DROPPED")
                            return False
            else:
                InternalLogger.get().critical("ERROR: No mapping")

        # manipulate leaving packet
        else:
            #look for existing mapping in TRACKER first (to ignore mapping for internal rIP if the connection is still being tracked)
            new_ip_tracked = None
            if self._track:
                new_ip_tracked = self.check_buffer(packet)
            if new_ip_tracked is not None:
                packet.src = new_ip_tracked
                InternalLogger.get().debug("SRC changed to  " +
                                           new_ip_tracked + " (from buffer)")
            #not in tracking, search in mapping
            else:
                new_ip = self._mapping.get(packet.src)
                if new_ip is not None:
                    packet.src = new_ip
                    InternalLogger.get().debug("SRC changed to " + new_ip +
                                               "(from mapping)")
                else:
                    InternalLogger.get().debug(
                        "Forwarding the leaving packet, SRC != MTD Host")
        return True
Example #23
0
    def handle_packet(self, pkt):
        """
        Forward packets to layer controllers and trackers

        :param pkt: Raw Packet
        """
        try:
            InternalLogger.get().debug("---Detected packet (" + str(pkt) + "),\t queue_num=" + str(self._queue_num))
            data = pkt.payload
            # Detect v4/v6 and load as IP object
            ip_packet = None
            try:
                ip_packet = IPv6(data)
                ip_version = 6
            except Exception as e:
                InternalLogger.get().debug("Exception in IPv6 Packet, trying IPv4")
            if ip_packet is None or ip_packet.version == 4:
                ip_packet = IP(data)
                ip_version = 4
            # Output data
            InternalLogger.get().debug("--Source: " + ip_packet.src + "\tDest: " + ip_packet.dst + "\tIPv" + str(ip_version))

            if self._debug_direct_forward:
                #Directly forward
                InternalLogger.get().debug("DEBUG: Forwarding")
                pkt.mangle()
            else:
                InternalLogger.get().debug("Checking layers")
                forward = self.check_layers(ip_packet)
                #check if the packet should be forwarded to the network stack (Attention: internal ip routes are responsible to forward it)
                if forward:
                    InternalLogger.get().debug("Recalculating checksums and length")
                    self.recalculate_checksums(ip_packet, ip_version)
                    InternalLogger.get().debug("Sending packet")
                    #Redirect packet to network stack
                    pkt.payload = raw(ip_packet)
                    pkt.mangle()
                else:
                    InternalLogger.get().debug("Dropped")
                    #Dont forward to localhost or another host, drop
                    pkt.drop()

        except Exception as e:
            InternalLogger.get().critical("Error: " + str(e), exc_info=True)
Example #24
0
def main():
    """
    COMPOSITION ROOT of the MTG / MTPG

    Load Configuration, start and configure PH/NAS components
    """

    conf_data = None
    with open('conf.json') as json_file:
        conf_data = json.load(json_file)

    whitelist = conf_data["whitelist"]
    enable_file_logging = conf_data["file_logging"]
    enable_debug_output = conf_data["debug_output"]
    InternalLogger.init(enable_file_logging, enable_debug_output)
    InternalLogger.get().info("Starting...")

    debug_forward = conf_data["debug_forward"]
    conf_data_nas = conf_data["nas"]
    conf_data_ph = conf_data["ph"]
    enable_nas = conf_data_nas["activate"]
    enable_ph = conf_data_ph["activate"]

    layer_controller_out = {}
    layer_controller_in = {}
    ip_translators = None
    dynamic_port_priority = None
    # Enable Network Address Shuffling
    if enable_nas:
        conf_data_nas = conf_data["nas"]
        InternalLogger.get().info("Starting NAS")
        dns_ttl = conf_data_nas["dns_ttl"]
        # Set Controllers
        dns = DnsTranslator(None, dns_ttl)

        conf_data_nas_tracking_honeypot = conf_data_nas["honeypot"]
        honeypot = conf_data_nas_tracking_honeypot["activate"]

        tracker = None
        conf_data_nas_tracking = conf_data_nas["tracking"]
        enable_nas_track = conf_data_nas_tracking["activate"]
        if enable_nas_track:
            #Enable Tracking
            tracker = NasConnectionTracker()
            layer_controller_out[70] = tracker
            layer_controller_in[30] = tracker

            #Enable Dynamic Port Priority
            conf_data_nas_tracking_priority = conf_data_nas_tracking[
                "dynamic_port_priority"]
            continue_list = conf_data_nas_tracking_priority["continue"]
            priority_list = conf_data_nas_tracking_priority["priority"]
            priority_def_list = conf_data_nas_tracking_priority["priority_def"]
            continue_all = conf_data_nas_tracking["continue_all"]
            dynamic_port_priority = DynamicPortPriority(
                continue_list, priority_list, priority_def_list, continue_all,
                tracker)

        ip_out = IPTranslatorNAS(None, whitelist, IO.OUTPUT, enable_nas_track,
                                 tracker, dynamic_port_priority)
        ip_in = IPTranslatorNAS(None, whitelist, IO.INPUT, enable_nas_track,
                                tracker, dynamic_port_priority)

        honeypot_v4_address = None
        honeypot_v6_address = None
        if honeypot:
            honeypot_v4_address = conf_data_nas_tracking_honeypot["v4_address"]
            honeypot_v6_address = conf_data_nas_tracking_honeypot["v6_address"]
            if honeypot_v6_address is None or honeypot_v4_address is None:
                InternalLogger.error("Honeypot address not set")
                return
            ip_in.set_honeypot(honeypot_v4_address, honeypot_v6_address)
            ip_out.set_honeypot(honeypot_v4_address, honeypot_v6_address)

        layer_controller_out[51] = dns
        layer_controller_out[50] = ip_out

        layer_controller_in[50] = ip_in

        ip_translators = [dns, ip_out, ip_in]

    # Enable PortHopping
    if enable_ph:
        InternalLogger.get().info("Starting PH")
        # Set Controllers
        enable_ph_client = conf_data_ph["client"]
        max_buffer = conf_data_ph["max_buffer"]
        hopping_period = conf_data_ph["hopping_period"]

        ph_function = RpahFunction(hopping_period, max_buffer)
        keymap = conf_data_ph["keymap"]
        subnets_server = conf_data_ph["ph_subnets_server"]
        #tracker needs to use ph function to preserve tracking
        # ph_function = TestPhFunction()
        ph_out = PortTranslatorPh(ph_function, IO.OUTPUT, whitelist,
                                  enable_ph_client, keymap, subnets_server)
        layer_controller_out[100] = ph_out

        ph_in = PortTranslatorPh(ph_function, IO.INPUT, whitelist,
                                 enable_ph_client, keymap, subnets_server)
        layer_controller_in[10] = ph_in

    if not (enable_nas or enable_ph):
        InternalLogger.get().warning("WARNING: PH and NAS not activated")

    incoming_data = IpController(1, layer_controller_in, debug_forward,
                                 IO.INPUT)
    incoming_data.start()
    leaving_data = IpController(2, layer_controller_out, debug_forward,
                                IO.OUTPUT)
    leaving_data.start()

    if enable_nas:
        # Start HF Controller
        if ip_translators is None:
            InternalLogger.get().debug("WARNING: No Translators")
        hf_receiver = conf_data_nas["receiver"]
        hopping_period = conf_data_nas["hopping_period"]
        controller = HfController(ip_translators, hf_receiver, hopping_period,
                                  dynamic_port_priority)
        controller.set_lf_mapping(None)
        controller.start()
        subnetmapping_receiver = [controller]

        rest_local = conf_data_nas["rest_iface"]
        InternalLogger.get().info("Starting rest at: " + rest_local)

        # Start Rest API
        api = Api(app)
        api.add_resource(LfMappingApi,
                         '/v1.0/nas_mapping',
                         endpoint='nas_mapping',
                         resource_class_kwargs={
                             'subnet_controller': subnetmapping_receiver
                         })
        Thread.start(run_flask(rest_local))