def handle_query(self, transaction_id, query_data): try: query_parser = parse.ParseQuery(query_data) parse_result = query_parser.parse_plain() query_name_list = parse_result[1]['QNAME'] query_type = parse_result[1]['QTYPE'] query_name = utils.get_domain_name_string(query_name_list) if self.enable_log: self.logger.write_log('query_parse_result:' + str(parse_result)) cache_query = None cached = False if self.enable_cache and query_name in self.cache and query_type in self.cache[query_name]: cache_query = self.cache[query_name][query_type] cache_time = cache_query[1] cache_ttl = cache_query[2] current_time = int(time.time()) if current_time - cache_time > cache_ttl: self.cache[query_name].pop(query_type) else: cached = True if cached: cache_query_result = cache_query[0] cache_query_result = bytes.fromhex(transaction_id) + cache_query_result[2:] sendback_address = self.dns_map[transaction_id][0] self.server.sendto(cache_query_result, sendback_address) self.dns_map.pop(transaction_id) else: if query_name in self.dns_config['dns_bypass']: upstream_object = self.bootstrap_dns_object upstream_object.query(query_data) elif self.dns_bypass_china: upstream_object = self.bootstrap_dns_object upstream_object.query(query_data) upstream_object = self.select_upstream() upstream_object.query(query_data) else: upstream_object = self.select_upstream() upstream_object.query(query_data) except IndexError as exc: print('[Error]', str(exc)) except KeyboardInterrupt: exit() except Exception as exc: print('[Error]', str(exc))
def start(self): try: while True: recv_data, recv_address = self.server.recvfrom(512) recv_header = parse.ParseHeader.parse_header(recv_data) if self.enable_log: self.logger.write_log('recv_data:' + str(recv_data)) transaction_id = recv_header['transaction_id'] if self.enable_log: self.logger.write_log('transaction_id:' + str(transaction_id)) if recv_header['flags']['QR'] == '0': self.dns_map[transaction_id] = [recv_address, 0] query_thread = threading.Thread(target=self.handle_query, args=(transaction_id, recv_data,)) query_thread.daemon = True query_thread.start() elif recv_header['flags']['QR'] == '1' and transaction_id in self.dns_map: response = self.handle_response(recv_data) sendback_address = self.dns_map[transaction_id][0] if self.dns_bypass_china and response[2]: if len(response[2]) > 1: ip_address = response[2][-1]['record'] else: ip_address = response[2][0]['record'] if self.dns_map[transaction_id][1] == 1 or ( utils.is_valid_ipv4_address(ip_address) and utils.is_subnet_address( 'filter_lists/chnroute.txt', ip_address) ): self.server.sendto(recv_data, sendback_address) self.dns_map.pop(transaction_id) elif self.dns_map[transaction_id][1] == 0: self.dns_map[transaction_id][1] = 1 continue else: self.server.sendto(recv_data, sendback_address) self.dns_map.pop(transaction_id) if self.enable_cache and response[2]: response_name = utils.get_domain_name_string(response[1]['QNAME']) if response_name != '': response_type = response[1]['QTYPE'] response_ttl = response[2][0]['ttl'] if response_name not in self.cache: self.cache[response_name] = {} self.cache[response_name][response_type] = [recv_data, int(time.time()), response_ttl] except socket.timeout as exc: print('[Error]', str(exc)) self.start() except KeyboardInterrupt: print('Stop Encrypted-DNS Resolver') exit() except Exception as exc: print('[Error]', str(exc)) self.start()
def handle_query(self, transaction_id, query_data): try: query_parser = parse.ParseQuery(query_data) parse_result = query_parser.parse_plain() query_name_list = parse_result[1]['QNAME'] query_type = parse_result[1]['QTYPE'] query_name = utils.get_domain_name_string(query_name_list) if self.enable_log: self.logger.write_log('query_parse_result:' + str(parse_result)) cache_query = None cached = False for item in self.hosts.keys(): if query_name == item or (item.startswith("include:") and item.lstrip("include:") in query_name): response_data = utils.struct_response(query_name, str(transaction_id), query_type, self.hosts[item][0], self.hosts[item][1]) sendback_address = self.dns_map[transaction_id][0] self.server.sendto(response_data, sendback_address) self.dns_map.pop(transaction_id) return if self.enable_cache and query_name in self.cache and query_type in self.cache[query_name]: cache_query = self.cache[query_name][query_type] cache_time = cache_query[1] cache_ttl = cache_query[2] current_time = int(time.time()) if current_time - cache_time > cache_ttl: self.cache[query_name].pop(query_type) else: cached = True if cached: cache_query_result = cache_query[0] cache_query_result = bytes.fromhex(transaction_id) + cache_query_result[2:] sendback_address = self.dns_map[transaction_id][0] self.server.sendto(cache_query_result, sendback_address) self.dns_map.pop(transaction_id) else: if query_name in self.dns_config['dns_bypass']: upstream_object = self.bootstrap_dns_object upstream_object.query(query_data) elif self.dns_bypass_china: upstream_object = self.bootstrap_dns_object upstream_object.query(query_data) upstream_object = self.select_upstream() upstream_object.query(query_data) else: upstream_object = self.select_upstream() upstream_object.query(query_data) except IndexError as exc: print('[Error]', str(exc)) except KeyboardInterrupt: print('Stop Encrypted-DNS Resolver') exit() except Exception as exc: print('[Error]', str(exc)) raise exc