def dns_response_for_sending(self):
     self.client_data_holder.parsed_dns_response.header.id = self.client_data_holder.parsed_dns_request.header.id
     self.client_data_holder.raw_dns_response = DNSRecord.pack(
         self.client_data_holder.parsed_dns_response)
     logger.debug(
         f"[Process: Packing Data For Sending], Request_Header_ID: [{self.client_data_holder.parsed_dns_request.header.id}], Response_Data: [{self.client_data_holder.raw_dns_response}]"
     )
 def fetch_from_cache(self):
     raw_dns_response = web_category_cache.get_from_cache(
         self.client_data_holder.unique_key)
     logger.debug(
         f"[Process: Fetching From Cache], Key: [{self.client_data_holder.unique_key}], Value: [{raw_dns_response}]"
     )
     self.client_data_holder.raw_dns_response = raw_dns_response
 def clear_cache(self):
     logger.debug(f"[Process: Clearing Cache], "
                  f"CurrentCacheSize: [{self.cache.currsize}], "
                  f"[MaxCacheSize: {self.cache.maxsize}], "
                  f"[CacheTTL: {self.cache.ttl}], "
                  f"[CacheTimer: {self.cache.timer}]")
     self.cache.clear()
    def start_server(self):
        logger.debug(
            f"Dns Service Running @ {self.DNS_SERVER_UDP_SOCKET.getsockname()} "
        )

        while True:
            try:
                dns_request, client_address = self.DNS_SERVER_UDP_SOCKET.recvfrom(
                    1024)
                ## Received Data from Socket
                #self.validate_and_handle_client(uniq_id, dns_request, client_address); ## Single Threaded
                handler_thread = Thread(
                    target=self.validate_and_handle_client,
                    args=(dns_request,
                          client_address))  ## Making it MultiThreaded
                #handler_thread.setName(f"Dns-Query-Handler-Thread-{uniq_id}")
                logger.debug(
                    f"[Process: Starting Thread: {handler_thread.getName()} with uniq_id: [{uniq_id}]]"
                )
                handler_thread.start()
                ## Start The Thread For Processing
            except ConnectionResetError as conn_reset:
                logger.error(
                    f"[Reason: ConnectionResetError]: [ERROR: {conn_reset}]")
            except KeyboardInterrupt as key_cancel:
                logger.error(
                    f"[Reason: KeyboardInterrupt]: [ERROR: {key_cancel}]")
                self.stop_server()
            except Exception as all_exception:
                logger.error(
                    f"[Reason: Exception]: [All Exceptions are handled here][ERROR: {all_exception}]"
                )
                logger.error(traceback.print_exc())
                self.stop_server()
 def init_xml_content(self):
     with open(self.config_file_name) as xml_config_file:
         self.xml_content = xml_config_file.read()
     logger.debug(
         f"Processed Data From [File:{self.config_file_name}], XML CONTENT DATA: =>"
     )
     logger.debug(self.xml_content)
     return self.xml_content
 def process_policy_check_for_dns_response(cls, client_data_holder):
     ## No Implementation there ALLOW for all
     client_data_holder.policy_status = "ALLOW"
     client_data_holder.unique_key = client_data_holder.requested_domain + "_" + client_data_holder.requested_query_type + "_" + client_data_holder.policy_status
     logger.debug(
         f"[Process: Policy Checking(Response) & Unique Key Rewrite], Unique Key: [{client_data_holder.unique_key}]  [Not Implemented]"
     )
     return client_data_holder
Example #7
0
 def send_response_to_client(self, client_address, raw_dns_response,
                             status_tag):
     logger.debug(
         f"[Reason:{status_tag}] Sending Response To [Client:{client_address}], "
         f"By [Server:{self.DNS_SERVER_UDP_SOCKET}], "
         f"[Data:{str(raw_dns_response)}]")
     self.wfile.write(
         raw_dns_response
     )  # Write Data To Client But is only Flushed when Finish is called
 def init_bs4_parsed_xml_content(self):
     parser_utility = 'html.parser'
     bs4_parsed_xml_content = BeautifulSoup(self.xml_content,
                                            parser_utility)
     self.bs4_parsed_xml_content = bs4_parsed_xml_content
     logger.debug(
         f"Processed Data From [Parser_Utility:{parser_utility}], [Lib: BeatifulSoup(BS4) Parsed CONTENT DATA: =>"
     )
     logger.debug(self.bs4_parsed_xml_content)
     return self.bs4_parsed_xml_content
 def get_dns_request_question_details(self, ):
     dns_question_1 = self.client_data_holder.parsed_dns_request.questions[
         0]
     dns_question_name = str(dns_question_1.qname)
     dns_question_type = str(dns_question_1.qtype)
     self.client_data_holder.requested_domain = dns_question_name
     self.client_data_holder.requested_query_type = dns_question_type
     logger.debug(
         f"Dns Question Section, Question[0]: [{dns_question_1}] : With Question: [{dns_question_name}] & Type: [{dns_question_type}] "
     )
 def cache_check(self):
     if web_category_cache.check_if_present(
             self.client_data_holder.unique_key):
         logger.debug(
             f"[Process: Checking In Cache(FOUND)], Key: [{self.client_data_holder.unique_key}], Value: [NOT SHOWN(Check This)]"
         )
         self.client_data_holder.cache_status = True
     else:
         logger.debug(
             f"[Process: Checking In Cache(NOT-FOUND)], Key: [{self.client_data_holder.unique_key}], Value: [NOT SHOWN(Check This)]"
         )
         self.client_data_holder.cache_status = False
    def dns_request_extractor(self):
        dns_request_header, dns_request_header_id, = self.get_dns_request_header_details(
            self.client_data_holder.parsed_dns_request.header)
        logger.debug(
            f"Dns Header Section: of ID: {dns_request_header_id}, Data: [{dns_request_header}]"
        )

        self.client_data_holder.dns_header_id = dns_request_header_id
        self.get_dns_request_question_details()

        unique_key = self.generate_key(
            self.client_data_holder.requested_domain,
            self.client_data_holder.requested_query_type)
        self.client_data_holder.unique_key = unique_key
    def process_dns_response(self):

        ip_list, cname_list, ptr_list = self.get_response_details(
            self.client_data_holder.parsed_dns_response.rr)
        logger.debug(
            f"[Process: Getting IP_LIST/CNAME_LIST/PTR_LIST], "
            f"Type: [{self.client_data_holder.requested_query_type}], "
            f"Data: [IP(v4/v6):[{ip_list}]], [CNAME:[{cname_list}]], [PTR:[{ptr_list}]]"
        )

        if ip_list:
            self.client_data_holder.response_ip_list = ','.join(ip_list)
        if cname_list:
            self.client_data_holder.response_cname_list = ','.join(cname_list)
        if ptr_list:
            self.client_data_holder.response_ptr_list = ','.join(ptr_list)
 def start_server(self):
     logger.debug(f"[Process: Starting Dns Server @ [{self.server_address}]");
     print(f"[Process: Starting Dns Server @ [{self.server_address}]");
     reason = None;
     try:
         self.serve_forever(); #Start The Server
     except ConnectionResetError as conn_reset:
         logger.error(f"[Reason: ConnectionResetError]: [ERROR: {conn_reset}]", exc_info=True); # Stack Trace the Exception
         reason = conn_reset;
     except KeyboardInterrupt as key_cancel:
         logger.error(f"[Reason: KeyboardInterrupt]: [ERROR: {key_cancel}]", exc_info=True); # Stack Trace the Exception
         reason = key_cancel;
     except Exception as all_exception:
         logger.error(f"[Reason: Exception]: [All Exceptions are handled here][ERROR: {all_exception}]", exc_info=True); # Stack Trace the Exception
         reason = all_exception;
     finally:
         self.stop_server(reason=reason)
    def process_policy_check_for_dns_request(cls, client_data_holder):
        ## No Implementation there ALLOW for all
        status = process_policy(client_data_holder=client_data_holder)
        print("Status: ", status)
        if status["status"] == "BLOCK":
            client_data_holder.policy_status = "BLOCK:" + status.get("type")
        else:
            client_data_holder.policy_status = "ALLOW:" + status.get("type")

        client_data_holder.unique_key = client_data_holder.requested_domain + "_" + client_data_holder.requested_query_type + "_" + client_data_holder.policy_status.split(
            ":")[0]

        logger.debug(
            f"[Process: Policy Checking(Request) & Unique Key Rewrite], Unique Key: [{client_data_holder.unique_key}] [Not Implemented] "
        )
        #print(f"[Process: Policy Checking(Request) & Unique Key Rewrite], Unique Key: [{client_data_holder.unique_key}] [Not Implemented] ");
        return client_data_holder
def process_policy(client_data_holder):
    dns_server_config_data_holder = DNS_SERVER_CONFIG_DATA_HOLDER
    #status = { "status": "ALLOW", "type": "Regex" } # Type: Regex or WebCategory
    status = process_block_policy(
        client_data_holder=client_data_holder,
        dns_server_config_data_holder=dns_server_config_data_holder)

    # If block True lets's check  Allow Status
    if status.get("block_status"):
        _status = process_allow_policy(
            client_data_holder=client_data_holder,
            dns_server_config_data_holder=dns_server_config_data_holder)
        logger.debug(f"Processed Allow Policy Result for Allow:{status}")
        if status.get("allow_status"):
            return {"status": "ALLOW", "type": _status.get("allow_type")}
        else:
            return {"status": "BLOCK", "type": status.get("block_type")}
    else:
        return {"status": "ALLOW", "type": "No-Block-Match"}
    def process_setup_config_section(self):
        section_content_xml = self.bs4_parsed_xml_content.find_all(
            'setup_config')
        logger.debug(f"Processing [Section:setup_config] Data:")
        logger.debug(section_content_xml)

        dns_server_udp_ip = section_content_xml[0].dns_server_udp_ip.getText(
        ).strip()
        dns_server_udp_port = section_content_xml[
            0].dns_server_udp_port.getText().strip()
        dns_server_tcp_ip = section_content_xml[0].dns_server_tcp_ip.getText(
        ).strip()
        dns_server_tcp_port = section_content_xml[
            0].dns_server_tcp_port.getText().strip()
        default_auth_dns_server_ip = section_content_xml[
            0].default_auth_dns_server_ip.getText().strip()
        default_auth_dns_server_port = section_content_xml[
            0].default_auth_dns_server_port.getText().strip()
        dns_server_recv_bytes_size = section_content_xml[
            0].dns_server_recv_bytes_size.getText().strip()
        dns_auth_server_recv_bytes_size = section_content_xml[
            0].dns_auth_server_recv_bytes_size.getText().strip()
        dns_server_log_debug_on_console = section_content_xml[
            0].dns_server_log_debug_on_console.getText().strip()
        dns_cache_size = section_content_xml[0].dns_cache_size.getText().strip(
        )
        dns_cache_ttl = section_content_xml[0].dns_cache_ttl.getText().strip()
        category_match_type = section_content_xml[
            0].category_match_type.getText().strip()
        return SetupConfigDataHolder(
            dns_server_udp_ip=dns_server_udp_ip,
            dns_server_udp_port=dns_server_udp_port,
            dns_server_tcp_ip=dns_server_tcp_ip,
            dns_server_tcp_port=dns_server_tcp_port,
            default_auth_dns_server_ip=default_auth_dns_server_ip,
            default_auth_dns_server_port=default_auth_dns_server_port,
            dns_server_recv_bytes_size=dns_server_recv_bytes_size,
            dns_auth_server_recv_bytes_size=dns_auth_server_recv_bytes_size,
            dns_server_log_debug_on_console=dns_server_log_debug_on_console,
            dns_cache_size=dns_cache_size,
            dns_cache_ttl=dns_cache_ttl,
            category_match_type=category_match_type)
    def process_blocked_section(self):
        blocked = 'blocked'
        section_blocked_xml = self.bs4_parsed_xml_content.find_all(blocked)
        logger.debug(f"Processing [Section: {blocked}] Data:")
        logger.debug(section_blocked_xml)

        block_policy_name = section_blocked_xml[0].block_policy_name.getText(
        ).strip()
        block_policy_description = section_blocked_xml[
            0].block_policy_description.getText().strip()
        block_policy_regex_pattern = section_blocked_xml[
            0].block_policy_regex_pattern.getText().strip()
        block_policy_webcategory_list = section_blocked_xml[
            0].block_policy_webcategory_list.getText().strip()

        return BlockedDataHolder(
            block_policy_name=block_policy_name,
            block_policy_description=block_policy_description,
            block_policy_regex_pattern=block_policy_regex_pattern,
            block_policy_webcategory_list=block_policy_webcategory_list)
    def process_allowed_section(self):
        allowed = 'allowed'
        section_allowed_xml = self.bs4_parsed_xml_content.find_all(allowed)
        logger.debug(f"Processing [Section: {allowed}] Data:")
        logger.debug(section_allowed_xml)

        allow_policy_name = section_allowed_xml[0].allow_policy_name.getText(
        ).strip()
        allow_policy_description = section_allowed_xml[
            0].allow_policy_description.getText().strip()
        allow_policy_regex_pattern = section_allowed_xml[
            0].allow_policy_regex_pattern.getText().strip()
        allow_policy_webcategory_list = section_allowed_xml[
            0].allow_policy_webcategory_list.getText().strip()

        return AllowedDataHolder(
            allow_policy_name=allow_policy_name,
            allow_policy_description=allow_policy_description,
            allow_policy_regex_pattern=allow_policy_regex_pattern,
            allow_policy_webcategory_list=allow_policy_webcategory_list)
 def handle_client(self, dns_request, client_address):
     logger.debug(
         f"Dns Request Received from "
         f"[Client:{client_address}], "
         f"By [Server:{self.DNS_SERVER_UDP_SOCKET.getsockname()}], "
         f"[Data:{str(dns_request)}] ")
     client_data_holder = ClientDataHolder(
         client_ip_address=client_address[0],
         client_socket_address=client_address,
         raw_dns_request=dns_request)
     client_data_holder.dns_start_time = fetch_current_unix_time()
     dns_handler = DnsHandler()
     client_data_holder = dns_handler.process(
         client_data_holder=client_data_holder)  # Send it To the Processor
     self.send_response_to_client(
         client_address, client_data_holder.raw_dns_response,
         f"CLIENT-{client_data_holder.policy_status}")
     client_data_holder.dns_end_time = fetch_current_unix_time()
     dns_process_time = (client_data_holder.dns_end_time -
                         client_data_holder.dns_start_time) * 1000
     logger.debug(f"[Process: Dns Request Handled] took "
                  f"[Raw: {dns_process_time} millis] "
                  f"[Round: {round(dns_process_time, 3)} millis]")
     client_data_holder.dns_process_time = round(dns_process_time, 3)
     logger.debug(client_data_holder)
     self.dns_handler.insert_to_access_db(
         client_data_holder=client_data_holder)
Example #20
0
    def handle_client(self, dns_request, client_address):
        logger.debug(f"Dns Request Received from "
                     f"[Client:{client_address}], "
                     f"By [Server:{self.DNS_SERVER_UDP_SOCKET}], "
                     f"[Data:{str(dns_request)}] ")
        self.client_data_holder = ClientDataHolder(
            client_ip_address=client_address[0],
            client_socket_address=client_address,
            raw_dns_request=dns_request)
        #self.client_data_holder.client_mac_address = self.get_mac(client_ip=client_address[0]) # Added to Get the Actual name of the query [Very Slow Function Do Not Use]
        self.client_data_holder.requested_domain_extracted = self.domain_name_extracted  # Added to Get the Actual name of the query

        self.client_data_holder.dns_start_time = fetch_current_unix_time()
        self.client_data_holder = DnsHandler().process(
            client_data_holder=self.client_data_holder
        )  # Send it To the Processor
        self.send_response_to_client(
            client_address, self.client_data_holder.raw_dns_response,
            f"CLIENT-{self.client_data_holder.policy_status}")
        self.client_data_holder.dns_end_time = fetch_current_unix_time()
        dns_process_time = (self.client_data_holder.dns_end_time -
                            self.client_data_holder.dns_start_time) * 1000

        logger.debug(f"[Process: Dns Request Handled] took "
                     f"[Raw: {dns_process_time} millis] "
                     f"[Round: {round(dns_process_time, 3)} millis]")
        self.client_data_holder.dns_process_time = round(dns_process_time, 3)

        logger.debug(self.client_data_holder)
Example #21
0
    def validate_and_dns_name_setup(self, dns_request, client_address):
        logger.debug(f"[Process : Validate & Dns Name Setup]")  ## Debugging
        validation_result = False
        validation_info = "Improper/Forged Dns Request"
        custom_parsed_dns_response = None
        try:
            parsed_dns_request = DNSRecord.parse(dns_request)
            req_dns_name = str(parsed_dns_request.questions[0].qname)
            req_dns_type = int(parsed_dns_request.questions[0].qtype)
            if req_dns_name in self.dns_name.keys():
                dns_name_to_set = self.dns_name[req_dns_name]
                logger.debug(f"IP ADDR LIST: {dns_name_to_set.split(',')}")
                custom_parsed_dns_response = DnsBuilder.create_dns_response(
                    parsed_dns_request=parsed_dns_request,
                    req_dns_name=req_dns_name,
                    req_dns_type=req_dns_type,
                    ip_address_list=dns_name_to_set.split(","))
                validation_info = ""
            else:
                validation_result = True
                validation_info = ""
                self.domain_name_extractor(
                    requested_domain_name=req_dns_name,
                    requested_domain_name_type=req_dns_type
                )  #Extract Proper Info From the Dns Requested Domain

        except (dnslib.buffer.BufferError,
                dnslib.dns.DNSError) as dns_parsing_error:
            logger.error(
                f"[Process: Validation By using parse()] "
                f"[Error: DnsRecord.parse() Exception, Data Received is INCORRECT, "
                f"Exception: [{dns_parsing_error}]",
                exc_info=True)
            # Enable StackTrace in Logs
            validation_info = validation_info + f", Exception: [{dns_parsing_error}]"
        except Exception as all_exception:
            logger.error(
                f"[Process: Validation By using parse()] "
                f"[Error: Unknown Exception] "
                f"Exception: [{all_exception}]",
                exc_info=True)
            # Enable StackTrace in Logs
            validation_info = validation_info + f", Exception: [{all_exception}]"
        finally:
            if validation_result:
                logger.debug(
                    f"Process Complete Validation INFO: [{validation_info}, {custom_parsed_dns_response}]"
                )
                return validation_result
            else:
                if validation_info == "":
                    self.send_response_to_client(
                        client_address=client_address,
                        raw_dns_response=DNSRecord.pack(
                            custom_parsed_dns_response),
                        status_tag=validation_info)
                return None
    def fetch_from_auth_dns_server(self):
        setup_config_data_holder = DNS_SERVER_CONFIG_DATA_HOLDER.setup_config_data_holder

        raw_dns_response = None

        if not self.client_data_holder.auth_server_ip_address:
            from_auth_dns_server = (
                setup_config_data_holder.default_auth_dns_server_ip,
                int(setup_config_data_holder.default_auth_dns_server_port))

        dns_auth_server_recv_bytes_size = setup_config_data_holder.dns_auth_server_recv_bytes_size

        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            sock.settimeout(2)
            # Set Time Out To 2 Seconds
            sock.sendto(self.client_data_holder.raw_dns_request,
                        from_auth_dns_server)
            logger.debug(f"[Process: Making UDP Conn to Remote Auth Server], "
                         f"Client Local Socket: [{sock}], "
                         f"Remote Socket: [{from_auth_dns_server}]"
                         f"[Socket Time Out: [{sock.gettimeout()}]]")
            raw_dns_response, server_address = sock.recvfrom(
                int(dns_auth_server_recv_bytes_size))
        except socket.timeout as socket_timeout:
            logger.debug(
                f"[Process: Socket TimedOut while fetching dns answer, Reason: [{socket_timeout}]], "
                f"[Do Not Cache This], [Sending the Same DnsRequest back To Client]"
            )
            # Need to Change This
            self.client_data_holder.dns_auth_server_timedout = True
            raw_dns_response = self.client_data_holder.raw_dns_request
        finally:
            sock.close()
            ##  Need some changes [CHECK THIS] [Add More Dns if one fails]
            logger.debug(
                f"[Process: Fetching From Auth Server], Key: [{self.client_data_holder.unique_key}], Value: [{raw_dns_response}]"
            )
            self.client_data_holder.raw_dns_response = raw_dns_response
    def process(self, client_data_holder):
        self.client_data_holder = client_data_holder
        self.generate_parsed_dns_request()

        self.process_dns_request()
        PolicyHandler.process_policy_check_for_dns_request(
            client_data_holder=client_data_holder
        )  # Request Filter set the query value to to ALLOW or BLOCK

        if client_data_holder.policy_status.split(":")[0] == "BLOCK":
            self.cache_check()
            # Check in Cache [Later change that it also return True or False]
            if client_data_holder.cache_status:
                self.fetch_from_cache(
                )  # Get From Cache [It Returns Raw Dns Response]
                return client_data_holder
                # now it can be send therefore return it
            else:
                custom_parsed_dns_reponse = DnsBuilder.create_dns_response(
                    parsed_dns_request=client_data_holder.parsed_dns_request,
                    req_dns_name=client_data_holder.requested_domain,
                    req_dns_type=client_data_holder.requested_query_type
                )  # Create a Block Response
                client_data_holder.parsed_dns_response = custom_parsed_dns_reponse
                self.dns_response_for_sending()
                return client_data_holder

        #self.cache_check_and_fetch()
        self.cache_check()

        # Getting the Raw Dns Response [From Cache ] OR [ From Auth Server]
        if self.client_data_holder.cache_status:
            self.fetch_from_cache()
        else:
            self.fetch_from_auth_dns_server()

        if client_data_holder.raw_dns_response:
            self.generate_parsed_dns_response()
        else:
            logger.error(
                f"[Reason: Cache OR Auth Server Had some Issue and return None "
                f"-> [{client_data_holder.raw_dns_response}], "
                f"[Temp Solution: Return Raw Dns Request as Raw Dns Response")
            client_data_holder.raw_dns_response = client_data_holder.raw_dns_request

        self.process_dns_response()
        PolicyHandler.process_policy_check_for_dns_response(
            client_data_holder=client_data_holder)  # Response Filter

        ## Left To Implement Response Filter if BLOCKED

        if not client_data_holder.cache_status and not client_data_holder.dns_auth_server_timedout:
            logger.debug(
                f"[Process: Adding Data To Cache], "
                f"Key: [{client_data_holder.unique_key}], "
                f"Value: [{client_data_holder.raw_dns_response}], "
                f"Cache Details: [{web_category_cache.show_cache()}], "
                f"[Socket TimeOut: [{client_data_holder.dns_auth_server_timedout}]] "
            )
            web_category_cache.add_to_cache(
                client_data_holder.unique_key,
                client_data_holder.raw_dns_response)
        else:
            logger.debug(
                f"[Process: Don't Add it To Cache], Cache Status: [{client_data_holder.cache_status}] "
                f"Key: [{client_data_holder.unique_key}], "
                f"Value: [{client_data_holder.raw_dns_response}], "
                f"Cache Details: [{web_category_cache.show_cache()}], "
                f"[Socket TimeOut: [{client_data_holder.dns_auth_server_timedout}]] "
            )

        self.dns_response_for_sending()
        return client_data_holder
 def send_response_to_client(self, client_address, dns_data, status_tag):
     logger.debug(
         f"[Reason:{status_tag}] Sending Response To [Client:{client_address}], By [Server:{self.DNS_SERVER_UDP_SOCKET.getsockname()}], [Data:{str(dns_data)}] "
     )
     self.DNS_SERVER_UDP_SOCKET.sendto(dns_data, client_address)
 def show_cache(self):
     logger.debug(f"[Process: Show Cache], "
                  f"CurrentCacheSize: [{self.cache.currsize}], "
                  f"[MaxCacheSize: {self.cache.maxsize}], "
                  f"[CacheTTL: {self.cache.ttl}], "
                  f"[CacheTimer: {self.cache.timer}]")
 def generate_parsed_dns_request(self):
     self.client_data_holder.parsed_dns_request = DNSRecord.parse(
         self.client_data_holder.raw_dns_request)
     logger.debug(
         f"Parsed Dns Request [RAW] to Dns Object [Dnslib]: \n{self.client_data_holder.parsed_dns_request.toZone()}\n\n"
     )
def get_dns_server_config_data_holder(config_file=None):
    if config_file:
        logger.debug(f"[IF] Config_File Provided: [{config_file}]")
    else:
        config_file = DnsServerStaticData.DNS_CONFIG_FILE_TEST
        logger.debug(
            f"[ELSE] Config_File is None, Therefore Set Config_File To: [{config_file}]"
        )

    config_parser = ConfigParser(config_file)
    dns_server_config_data_holder = DnsServerConfigDataHolder()
    for one_config_section in ConfigParser.CONFIG_SECTION:
        if one_config_section == "setup_config":
            logger.debug(f"Processing [Section: {one_config_section}]")
            setup_config_data_holder = config_parser.process_setup_config_section(
            )
            logger.debug("[Holder: SetupConfigDataHolder] Data:")
            logger.debug(setup_config_data_holder)
            dns_server_config_data_holder.setup_config_data_holder = setup_config_data_holder
        elif one_config_section == "blocked":
            logger.debug(f"Processing [Section: {one_config_section}]")
            blocked_data_holder = config_parser.process_blocked_section()
            logger.debug("[Holder: BlockedDataHolder] Data:")
            logger.debug(blocked_data_holder)
            dns_server_config_data_holder.blocked_data_holder = blocked_data_holder
        elif one_config_section == "allowed":
            logger.debug(f"Processing [Section: {one_config_section}]")
            allowed_data_holder = config_parser.process_allowed_section()
            logger.debug("[Holder: AllowedDataHolder] Data:")
            logger.debug(allowed_data_holder)
            dns_server_config_data_holder.allowed_data_holder = allowed_data_holder
        else:
            logger.debug(
                f"[Reason: Implementation Remaining] NOT Processing [Section: {one_config_section}]"
            )
    return dns_server_config_data_holder
def process_block_policy(
    client_data_holder,
    dns_server_config_data_holder,
):

    status = {"block_status": True, "block_type": "Regex"}
    #blocked_data_holder: BlockedDataHolder = dns_server_config_data_holder.blocked_data_holder # Good Way for Type Check
    blocked_data_holder = dns_server_config_data_holder.blocked_data_holder

    blocked_regex = blocked_data_holder.block_policy_regex_pattern
    blocked_webcategory_list = blocked_data_holder.block_policy_webcategory_list.split(
        ',')
    logger.debug(
        f"block_regex: [{blocked_regex}], block_webcategory_list: [{blocked_webcategory_list}] "
    )

    # No pattern in BLOCK & No Category Specified, Block ALL, can create problems, But Whitelist [Regex, WebCategory] needs to be Maintained properly then
    if blocked_regex.pattern.strip() == '' and not blocked_webcategory_list:
        status["block_status"] = True
        status["block_type"] = "Regex"
        logger.debug(
            f"MATCHED[ALL], BLOCK[ALL], Since EMPTY/SPACE, blocked_regex: [{blocked_regex}], Status: [{status}], block_webcategory_list: [{blocked_webcategory_list}] "
        )
        return status

    if blocked_regex.search(client_data_holder.requested_domain_extracted
                            ):  # Using Function: search() later changed
        status["block_status"] = True
        status["block_type"] = "Regex"
        logger.debug(
            f"Matched[BLOCKED:{status}], With RequestDomainExtracted:[{client_data_holder.requested_domain_extracted}]"
        )
    else:
        status["block_status"] = False
        status["block_type"] = "No-Regex-Match"
        logger.debug(
            f"NOT Matched[BLOCKED:{status}], With RequestDomainExtracted:[{client_data_holder.requested_domain_extracted}]"
        )

        if client_data_holder.web_category_list:
            logger.debug(
                f"[Process: Checking With Category], Client_WebCategoryList:[{client_data_holder.web_category_list}]"
            )

            if client_data_holder.web_category_list == list:
                webcategory_list = client_data_holder.web_category_list
            else:
                webcategory_list = client_data_holder.web_category_list.split(
                    ',')

            if bool(
                    set(webcategory_list).intersection(
                        blocked_webcategory_list)):
                status["block_status"] = True
                status["block_type"] = "WebCategory"
                logger.debug(
                    f"Matched[BLOCKED:{status}]: block_webcategory_list:[{blocked_webcategory_list}] With Client_WebCategoryList:[{webcategory_list}]"
                )
            else:
                logger.debug(
                    f"NOT Matched[BLOCKED:{status}]: block_webcategory_list:[{blocked_webcategory_list}] With Client_WebCategoryList:[{webcategory_list}]"
                )
        else:
            logger.debug(
                f"[Process: Category Is Empty], Client_WebCategoryList:[{client_data_holder.web_category_list}]"
            )

    return status
 def generate_key(self, q_name, q_type):
     key = q_name + "_" + q_type
     logger.debug(
         f"[Process: Generating Partial Key Before Policy Results], Unique_Key: [{key}]  "
     )
     return key
def process_allow_policy(client_data_holder, dns_server_config_data_holder):

    status = {"allow_status": True, "allow_type": "Regex"}
    # Process Allowed Section
    #allowed_data_holder: BlockedDataHolder = dns_server_config_data_holder.allowed_data_holder
    allowed_data_holder = dns_server_config_data_holder.allowed_data_holder

    allowed_regex = allowed_data_holder.allow_policy_regex_pattern
    allowed_webcategory_list = allowed_data_holder.allow_policy_webcategory_list.split(
        ',')
    logger.debug(
        f"allowed_regex: [{allowed_regex}], allowed_webcategory_list: [{allowed_webcategory_list}] "
    )

    # No pattern in ALLOW Does not work to allow all
    if allowed_regex.pattern.strip() == '' and not allowed_webcategory_list:
        status["allow_status"] = False
        status["allow_type"] = "Regex"
        logger.debug(
            f"MATCHED[ALL], BLOCK[ALL], Since EMPTY/SPACE, blocked_regex: [{allowed_regex}], Status: [{status}], block_webcategory_list: [{allowed_webcategory_list}] "
        )
        return status

    if allowed_regex.search(client_data_holder.requested_domain_extracted
                            ):  # Using search later changed
        status["allow_status"] = True
        status["allow_type"] = "Regex"
        logger.debug(
            f"Matched[ALLOWED:{status}], Regex:[{allowed_regex}] With RequestDomainExtracted:[{client_data_holder.requested_domain_extracted}]"
        )
    else:
        status["allow_status"] = False
        status["allow_type"] = "No-Regex-Match"
        logger.debug(
            f"NOT Matched[ALLOWED:{status}], Regex:[{allowed_regex}] With RequestDomainExtracted:[{client_data_holder.requested_domain_extracted}]"
        )

        if client_data_holder.web_category_list:
            logger.debug(
                f"[Process: Checking With Category], Client_WebCategoryList:[{client_data_holder.web_category_list}]"
            )

            if client_data_holder.web_category_list == list:
                webcategory_list = client_data_holder.web_category_list
            else:
                webcategory_list = client_data_holder.web_category_list.split(
                    ',')

            if bool(
                    set(webcategory_list).intersection(
                        allowed_webcategory_list)):
                status["allow_status"] = True
                status["allow_type"] = "WebCategory"
                logger.debug(
                    f"Matched[ALLOWED:{status}]: allowed_webcategory_list:[{allowed_webcategory_list}] With Client_WebCategoryList:[{webcategory_list}]"
                )
            else:
                logger.debug(
                    f"NOT Matched[BLOCKED:{status}]: allowed_webcategory_list:[{allowed_webcategory_list}] With Client_WebCategoryList:[{webcategory_list}]"
                )
        else:
            logger.debug(
                f"[Process: Category Is Empty], Client_WebCategoryList:[{client_data_holder.web_category_list}]"
            )

    return status