def finish(self): super().finish( ) # Flush the Data to Client & Then Write To Database [Currently Sqlite is Used] try: database_handler = AccessDatabaseHandler() with database_handler.get_connection( ) as db_connection: # Db Context Way to Insert and Commit Quickly AccessDatabaseHandler.insert_to_access_db( db_connection=db_connection, client_data_holder=self.client_data_holder) ## Insert Into DB ## Commit [Currently each insert is committed we we actually later on change it to 1000 Transaction and then commit it] database_handler.close_db_connection() except AttributeError as client_data_holder_not_present: logger.error( f"[Reason: AttributeError], Details: [{client_data_holder_not_present}]" ) except Exception as all_exception: print( f"[EXCEPTION: {all_exception}], client_Data_holder to insert: ", self.client_data_holder) logger.error( f"[EXCEPTION: {all_exception}], client_Data_holder to insert: {self.client_data_holder}" )
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 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 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 stop_server(self, reason): logger.error(f"[Reason: {reason}] Closing/Shutting Dns Service"); self.server_close() exit();
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 stop_server(self): logger.error( "[Reason: KeyboardInterrupt] Closing/Shutting Dns Service") exit()