Example #1
0
    def process(self):
        """
        Start listening and processing Queries.
        :return:
        """
        # TODO: need to figure out what to do when ony IPv4 address is to be used
        s_udp6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
        s_tcp6 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
        s_udp6.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s_tcp6.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self._sockets.append(s_udp6)
        self._sockets.append(s_tcp6)

        try:
            # kernel allows to receive IPv4 packets
            try:
                s_udp6.bind((self._listen_address, self._listen_port))
                s_tcp6.bind((self._listen_address, self._listen_port))
            except socket.error as e:
                # [Errno 13] Permission denied
                if e.errno == 13:
                    logger.error('You need to be root to bind to port %s',
                                 str(self._listen_port))
                # [Errno -9] Address family for hostname not supported
                elif e.errno == -9:
                    logger.error(
                        "Only IPv4 addresses or 'localhost' is supported at this point."
                    )
                raise BrokenDNSProxyError(e.strerror)

            s_tcp6.listen(0)

            logger.info('Listening on port %s...', str(self._listen_port))

            while True:
                ready_r, ready_w, _ = select.select(self._sockets, [], [])

                for s in ready_r:
                    client = Client(s)
                    msg = client.msg()

                    # sample code sending a response to the client
                    upstream_server = random.choice(self._upstream_servers)
                    logger.debug("Forwarding Query to upstream server '%s'",
                                 str(upstream_server))
                    response = dns.query.udp(msg, upstream_server)

                    # modify the message for client
                    self._modification_chain.run_modifiers(response)

                    client.send(response)
        finally:
            for s in self._sockets:
                s.close()
Example #2
0
    def _handle_datagram_socket(self, server_socket):
        """

        :param server_socket:
        :return:
        """
        # 16bit max udp length limit
        self._client_msg_raw, self._client_addr = server_socket.recvfrom(2**16)
        logger.debug('Received UDP data from: %s', str(self._client_addr))
        self._client_msg_len = len(self._client_msg_raw)
        logger.debug('UDP Query of length %s', str(self._client_msg_len))
        self._client_sock = server_socket
Example #3
0
    def _handle_datagram_socket(self, server_socket):
        """

        :param server_socket:
        :return:
        """
        # 16bit max udp length limit
        self._client_msg_raw, self._client_addr = server_socket.recvfrom(2**16)
        logger.debug('Received UDP data from: %s', str(self._client_addr))
        self._client_msg_len = len(self._client_msg_raw)
        logger.debug('UDP Query of length %s', str(self._client_msg_len))
        self._client_sock = server_socket
    def run_modifiers(self, dns_message):
        """

        :param dns_message:
        :return:
        """
        logger.debug("Running total '%d' modifiers...", len(self._modifiers))

        for mod in self._modifiers:
            logger.debug("Running '%s' modifier...", mod.config_section_name())
            dns_message = mod.modify(dns_message)

        return dns_message
    def run_modifiers(self, dns_message):
        """

        :param dns_message:
        :return:
        """
        logger.debug("Running total '%d' modifiers...", len(self._modifiers))

        for mod in self._modifiers:
            logger.debug("Running '%s' modifier...", mod.config_section_name())
            dns_message = mod.modify(dns_message)

        return dns_message
Example #6
0
    def process(self):
        """
        Start listening and processing Queries.
        :return:
        """
        # TODO: need to figure out what to do when ony IPv4 address is to be used
        s_udp6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
        s_tcp6 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
        s_udp6.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s_tcp6.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self._sockets.append(s_udp6)
        self._sockets.append(s_tcp6)

        try:
            # kernel allows to receive IPv4 packets
            try:
                s_udp6.bind((self._listen_address, self._listen_port))
                s_tcp6.bind((self._listen_address, self._listen_port))
            except socket.error as e:
                # [Errno 13] Permission denied
                if e.errno == 13:
                    logger.error('You need to be root to bind to port %s', str(self._listen_port))
                # [Errno -9] Address family for hostname not supported
                elif e.errno == -9:
                    logger.error("Only IPv4 addresses or 'localhost' is supported at this point.")
                raise BrokenDNSProxyError(e.strerror)

            s_tcp6.listen(0)

            logger.info('Listening on port %s...', str(self._listen_port))

            while True:
                ready_r, ready_w, _ = select.select(self._sockets, [], [])

                for s in ready_r:
                    client = Client(s)
                    msg = client.msg()

                    # sample code sending a response to the client
                    upstream_server = random.choice(self._upstream_servers)
                    logger.debug("Forwarding Query to upstream server '%s'", str(upstream_server))
                    response = dns.query.udp(msg, upstream_server)

                    # modify the message for client
                    self._modification_chain.run_modifiers(response)

                    client.send(response)
        finally:
            for s in self._sockets:
                s.close()
    def __init__(self, configuration):
        """

        :param configuration:
        :return:
        """
        self._modifiers = list()
        modifiers_list = configuration.getlist(GlobalConfig.config_section_name(), GlobalConfig.CONFIG_MODIFIERS)

        for mod_name in modifiers_list:
            mod = get_modifier_by_name(mod_name)
            if not mod:
                raise BrokenDNSProxyError("Modifier '{0}' does not exist!".format(mod_name))
            logger.debug("Adding modifier '%s' to Modification Chain", mod_name)
            self._modifiers.append(mod(configuration))
Example #8
0
    def __init__(self, server_socket):
        """
        Constructor

        :param server_socket: The socket object on which we have possible client pending
        :return: None
        """
        if server_socket.type not in (socket.SOCK_DGRAM, socket.SOCK_STREAM):
            raise BrokenDNSProxyError("Pending client on socket with wrong type '{0}'".format(server_socket.type))

        self._receive_client_msg(server_socket)
        self._client_msg = dns.message.from_wire(self._client_msg_raw)
        logger.debug("Received DNS message:\n"
                     "-----------------------------\n"
                     "%s\n"
                     "-----------------------------", str(self._client_msg))
Example #9
0
    def __init__(self, cli_conf):
        self._config = ConfigParser()
        self._add_commandline_arguments(cli_conf)
        self._read_proxy_default_config()

        config_abs_path = os.path.abspath(cli_conf.config_path)

        try:
            self._config.read(config_abs_path)[0]
        except IndexError:
            logger.warning("Configuration file '%s' could not be read... "
                           "Using ONLY default settings", config_abs_path)
        else:
            logger.debug("Using configuration from '%s'", config_abs_path)

        # include configuration for all modifiers
        self._read_modifiers_default_config()
Example #10
0
    def send(self, msg):
        """
        Send the msg as a response to the client query.

        :param msg: DNS Message object
        :return: None
        """
        logger.debug(
            'Sending message to client %s:\n'
            '-----------------------------\n'
            '%s\n'
            '-----------------------------', str(self._client_addr), str(msg))

        if self._client_sock.type == socket.SOCK_STREAM:
            self._send_stream(msg)
        elif self._client_sock.type == socket.SOCK_DGRAM:
            self._send_datagram(msg)
Example #11
0
    def send(self, msg):
        """
        Send the msg as a response to the client query.

        :param msg: DNS Message object
        :return: None
        """
        logger.debug('Sending message to client %s:\n'
                     '-----------------------------\n'
                     '%s\n'
                     '-----------------------------',
                     str(self._client_addr), str(msg))

        if self._client_sock.type == socket.SOCK_STREAM:
            self._send_stream(msg)
        elif self._client_sock.type == socket.SOCK_DGRAM:
            self._send_datagram(msg)
Example #12
0
    def __init__(self, cli_conf):
        self._config = ConfigParser()
        self._add_commandline_arguments(cli_conf)
        self._read_proxy_default_config()

        config_abs_path = os.path.abspath(cli_conf.config_path)

        try:
            self._config.read(config_abs_path)[0]
        except IndexError:
            logger.warning(
                "Configuration file '%s' could not be read... "
                "Using ONLY default settings", config_abs_path)
        else:
            logger.debug("Using configuration from '%s'", config_abs_path)

        # include configuration for all modifiers
        self._read_modifiers_default_config()
    def __init__(self, configuration):
        """

        :param configuration:
        :return:
        """
        self._modifiers = list()
        modifiers_list = configuration.getlist(
            GlobalConfig.config_section_name(), GlobalConfig.CONFIG_MODIFIERS)

        for mod_name in modifiers_list:
            mod = get_modifier_by_name(mod_name)
            if not mod:
                raise BrokenDNSProxyError(
                    "Modifier '{0}' does not exist!".format(mod_name))
            logger.debug("Adding modifier '%s' to Modification Chain",
                         mod_name)
            self._modifiers.append(mod(configuration))
Example #14
0
    def _handle_stream_socket(self, server_socket):
        """

        :param server_socket:
        :return:
        """
        self._client_sock, self._client_addr = server_socket.accept()
        logger.debug('TCP client %s connected', str(self._client_addr))

        self._client_msg_len = struct.unpack('!H', self._client_sock.recv(2))[0]
        logger.debug('TCP Query of length %s', str(self._client_msg_len))

        while len(self._client_msg_raw) < self._client_msg_len:
            # read all data
            chunk = self._client_sock.recv(self._client_msg_len - len(self._client_msg_raw))
            if not chunk:
                raise BrokenDNSProxyError('Unable to get all TCP data')
            self._client_msg_raw += chunk
Example #15
0
    def __init__(self, server_socket):
        """
        Constructor

        :param server_socket: The socket object on which we have possible client pending
        :return: None
        """
        if server_socket.type not in (socket.SOCK_DGRAM, socket.SOCK_STREAM):
            raise BrokenDNSProxyError(
                "Pending client on socket with wrong type '{0}'".format(
                    server_socket.type))

        self._receive_client_msg(server_socket)
        self._client_msg = dns.message.from_wire(self._client_msg_raw)
        logger.debug(
            "Received DNS message:\n"
            "-----------------------------\n"
            "%s\n"
            "-----------------------------", str(self._client_msg))
Example #16
0
    def _handle_stream_socket(self, server_socket):
        """

        :param server_socket:
        :return:
        """
        self._client_sock, self._client_addr = server_socket.accept()
        logger.debug('TCP client %s connected', str(self._client_addr))

        self._client_msg_len = struct.unpack('!H',
                                             self._client_sock.recv(2))[0]
        logger.debug('TCP Query of length %s', str(self._client_msg_len))

        while len(self._client_msg_raw) < self._client_msg_len:
            # read all data
            chunk = self._client_sock.recv(self._client_msg_len -
                                           len(self._client_msg_raw))
            if not chunk:
                raise BrokenDNSProxyError('Unable to get all TCP data')
            self._client_msg_raw += chunk
Example #17
0
 def run(self):
     logger.debug("Staring proxy server '%s'", str(self._server))
     self._server.process()
    def modify(self, dns_message):
        """
        Method modifying the DNS message, based on Modifier configuration

        :param dns_message: dns message object to modify
        :return: possibly modified dns message object
        """
        # go through all flags in settings and set/clear/do nothing with the flag
        # AA  Authoritative Answer [RFC 1035]
        if self._aa_flag is not None:
            if self._aa_flag:
                logger.debug("Setting AA flag")
                dns_message.flags |= dns.flags.AA
            else:
                logger.debug("Clearing AA flag")
                dns_message.flags &= ~dns.flags.AA
        # TC  Truncated Response   [RFC 1035]
        if self._tc_flag is not None:
            if self._tc_flag:
                logger.debug("Setting TC flag")
                dns_message.flags |= dns.flags.TC
            else:
                logger.debug("Clearing TC flag")
                dns_message.flags &= ~dns.flags.TC
        # RD  Recursion Desired    [RFC 1035]
        if self._rd_flag is not None:
            if self._rd_flag:
                logger.debug("Setting RD flag")
                dns_message.flags |= dns.flags.RD
            else:
                logger.debug("Clearing RD flag")
                dns_message.flags &= ~dns.flags.RD
        # RA  Recursion Allowed    [RFC 1035]
        if self._ra_flag is not None:
            if self._ra_flag:
                logger.debug("Setting RA flag")
                dns_message.flags |= dns.flags.RA
            else:
                logger.debug("Clearing RA flag")
                dns_message.flags &= ~dns.flags.RA
        # AD  Authentic Data       [RFC 4035]
        if self._ad_flag is not None:
            if self._ad_flag:
                logger.debug("Setting AD flag")
                dns_message.flags |= dns.flags.AD
            else:
                logger.debug("Clearing AD flag")
                dns_message.flags &= ~dns.flags.AD
        # CD  Checking Disabled    [RFC 4035]
        if self._cd_flag is not None:
            if self._cd_flag:
                logger.debug("Setting CD flag")
                dns_message.flags |= dns.flags.CD
            else:
                logger.debug("Clearing CD flag")
                dns_message.flags &= ~dns.flags.CD
        # DO  DNSSEC answer OK [RFC 4035][RFC 3225]
        if self._do_flag is not None:
            if self._do_flag:
                # enable EDNS if not enabled
                if dns_message.edns == -1:
                    logger.debug("EDNS0 not used... enabling")
                    dns.message.use_edns()
                logger.debug("Setting DO flag")
                dns_message.ednsflags |= dns.flags.DO
            else:
                logger.debug("Clearing DO flag")
                dns_message.ednsflags &= ~dns.flags.DO