def query( self, name, src_ip ): m = message.make_query( name, 1, 1 ) try: query.udp( m, '224.0.0.251', port=5353, timeout=20, source_port=5353, source=src_ip ) except dns.exception.Timeout: return False return True
def update(self, hostname, newhostname, ttl, rtype, resolveto): """Throws all exceptions upstream.""" nsupdate = update.Update(str(self.domain)) nsupdate.delete(str(hostname)) nsupdate.delete(str(newhostname)) nsupdate.add(str(newhostname), int(ttl), str(rtype), str(resolveto)) query.udp(nsupdate, self.server)
def get_NS(self, qname): # first, get all NS record q = message.make_query(qname, dnslib.QTYPE.A) IPlist = [] count = 0 while True and count < 3: try: msg = query.udp(q, DNSlist[0], timeout=1) except exception.Timeout: count += 1 continue break if count >= 3: logging.warning("Getting NS(A) %s failed, too many retries", qname) return ([], dnslib.RCODE.NXDOMAIN) answer = None for anss in msg.answer: #print "Type", rdatatype.to_text(anss.to_rdataset().rdtype) if anss.to_rdataset().rdtype == dnslib.QTYPE.A: #match record type # logging.debug("reply %s", anss) answer = anss if answer is None: logging.warning("Getting NS(A) %s failed, no NS(A)", qname) return ([], dnslib.RCODE.NXDOMAIN) for ans in answer: IPlist.append(ans.to_text()) return IPlist
def tryquery(q, server): rt = 0 while True: try: return query.udp(q, server, timeout=2) except exception.Timeout: rt = rt + 1
def get_master_ns(name, server=resolver.get_default_resolver().nameservers[0]): try: response = resolver.resolve(name, "SOA") return response.response.answer[0][0].mname.to_text() except resolver.NoAnswer: try: server_name = gethostbyaddr(server)[0] message, address = query_data(name, server_name, "SOA") response = query.udp(message, address) return response.authority[0].to_rdataset()[0].mname.to_text() except: return False except: return False
def fetch(dns_index_req): dns_index = dns_index_req[0] domain = dns_index_req[1] query_type = dns_index_req[2] q = message.make_query(domain, query_type) rcode = q.rcode() count = 0 while True and count < 3: try: msg = query.udp(q, DNSlist[dns_index], timeout=1) except exception.Timeout: count += 1 continue break if count >= 3: return ([], rcode) ips = [] #print msg.answer answer = None for anss in msg.answer: #print "Type", rdatatype.to_text(anss.to_rdataset().rdtype) if anss.to_rdataset().rdtype == query_type: #match record type answer = anss if answer is None: return (ips, rcode) for ans in answer: ips.append(ans.to_text()) return (ips, rcode)
def dns_response(self, domain, nameserver, retries=0): record_types = (rdatatype.NS, rdatatype.A, rdatatype.AAAA) records = [] rcodes = {} for rtype in record_types: try: request = dnsmessage.make_query(domain, rtype) sourceIP = self.get_source_ip() response_data = dnsquery.udp(q=request, where=nameserver, timeout=float( constants.REQUEST_TIMEOUT), source=sourceIP) rcodes[rtype] = response_data.rcode() records += response_data.answer + response_data.additional + response_data.authority except: if retries < int(constants.REQUEST_TRIES): return self.dns_response(domain, nameserver, retries + 1) else: rcodes['timeout'] = True return {"records": "", "rcodes": rcodes} return { "records": "\n".join([record.to_text() for record in records]), "rcodes": rcodes }
def return_response(name, server): name_message, server_addr = query_data(name, server, "A") response = query.udp(name_message, server_addr, 2.0) return response
def notify(nameserver , qname): request = make_notify(qname) response = query.udp(request, nameserver, timeout=3) rcode = response.rcode() if rcode == 0: logging.info('notifying server {} for zone {} success'.format(nameserver, qname)) else: logging.error('notifying server {} for zone {} fail, reason {}'.format(nameserver, qname, dns.rcode.to_text(rcode)))
def return_response_norecurse(name, server): name_message, server_addr = query_data(name, server, "A") name_message.flags = 0 response = query.udp(name_message, server_addr, 2.0) return response
def query(self, message, verify=True): try: if self.type == "tcp": response = query.tcp(message, self.host, port=self.port) elif self.type == "udp": response = query.udp(message, self.host, port=self.port) if self.verify(message): return response except: return None
def handle(self, data, addr): logging.info("Handling request for %s" % str(addr)) request = message.from_wire(data) name = self._name_from_message(request) if name in self.config['mapping']: logging.debug("Found %s in config file" % name) return self._make_response_for(request, name, self.config['mapping'][name]) else: logging.debug("Resolved %s from real dns" % name) return query.udp(request, self.config['general']['nameserver'])
def tryquery(q, server): while 1: try: return query.udp(q, server, timeout=2) except KeyboardInterrupt: print >> sys.stderr, '\naborted, partial results follow' pass except SystemExit: sys.exit(0) except exception.Timeout: pass
def get_tld(domain): for ns in ROOT_SERVERS: try: res = query.udp(message.make_query(domain, rdatatype.NS), ns) return get_next_ns(res) except query.BadResponse: if ns == ROOT_SERVERS[-1]: print("Something has gone horribly wrong, all root DNS servers are down.") exit(1) continue print("Cannot get TLD of %s" % domain) return None
def dnssec_check(domain, nameservers=False): """ Dig and use name servers from response to perform a DNSSEC validation Arguments: domain (str): domain to be validated nameservers (dict, optional): {name: ip} for authoritative nameservers Returns: ((bool), (response or None)) Raises: AttributeError: 'NoneType' object has no attribute 'answer' (res) IndexError: list index out of range (res.answer) """ if not nameservers: try: info = probe(domain) nameservers = info[domain.strip('www.') + '.']['NS'] except Exception as e: raise e req, res, answered = None, None, False for k, v in nameservers.items(): # get dns key for zone req = message.make_query(domain, rdatatype.DNSKEY, want_dnssec=True) res = query.udp(req, v) # if response code is 0 if not res.rcode(): if res.answer: # answer will have two RRSETs, DNSKEY and RRSIG if len(res.answer) == 2: answered = True break if answered: # create the dns.name object name = dns_name.from_text(domain) try: dnssec.validate(res.answer[0], res.answer[1], {name: res.answer[0]}) except dnssec.ValidationFailure: # be wary and do cautious something return False, res except Exception as e: raise e else: # all ok, valid self signed dnssec key for domain return True, res else: return False, None
def run(self): dns_index_req = self.dns_index_req dns_index = dns_index_req[0] domain = dns_index_req[1] query_type = dns_index_req[2] queue = dns_index_req[3] request = dns_index_req[4] reply_callback = dns_index_req[5] flag = dns_index_req[6] q = message.make_query(domain, query_type) q.id = request.header.id rcode = q.rcode() count = 0 start = time.time() * 1000 while True and count < 3: try: msg = query.udp(q, DNSlist[dns_index], timeout=1, flag=flag, r_callback=reply_callback) except exception.Timeout: count += 1 continue break if count >= 3: logging.warning("Worker thread %d too many retries", dns_index) queue.put(([], rcode)) return rcode ips = [] answer = None logging.debug("Worker thread %d gets reply %s", dns_index, msg.answer) for anss in msg.answer: #print "Type", rdatatype.to_text(anss.to_rdataset().rdtype) if anss.to_rdataset().rdtype == query_type: #match record type # logging.debug("reply %s", anss) answer = anss if answer is None: logging.warning("Worker thread %d empty response for %s",\ dns_index, domain) queue.put(([], rcode)) return 1 for ans in answer: ips.append(ans.to_text()) end = time.time() * 1000 logging.debug("Worker thread %d got answer, delay: %dms", dns_index, end - start) queue.put((ips, rcode)) #time.sleep(0) return 0
def resolve(self, message: Message) -> Message: maximum = 4 timeout = 0.4 response_message = 0 if self.name_server == 'internal': self.name_server = resolver.get_default_resolver().nameservers[0] done = False tests = 0 while not done and tests < maximum: try: response_message = query.udp(message, self.name_server, timeout=timeout) done = True except exception.Timeout: tests += 1 return response_message
def tryquery(target): global queries # pick a random dns server dns_server = random.choice(dns_server_list) q = message.make_query(target, 'PTR') while True: try: queries = queries + 1 response = query.udp(q, dns_server, timeout=2) return response except exception.Timeout: # change dns server if the current query timeout dns_server = random.choice(dns_server_list) except Exception: dns_server = random.choice(dns_server_list)
def get_ns(domain): """ Test to get the full zone file :param domain: :return: """ info = [] hosts = [] try: mess = message.make_query(domain, rdatatype.NS) response = query.udp(mess, "8.8.8.8") info.append("{0}".format(response)) except: info.append("Error in ns lookup") submit = (info, hosts) return submit
def run(self): dns_index_req = self.dns_index_req dns_index = dns_index_req[0] domain = dns_index_req[1] query_type = dns_index_req[2] queue = dns_index_req[3] request = dns_index_req[4] reply_callback = dns_index_req[5] flag = dns_index_req[6] q = message.make_query(domain, query_type) q.id = request.header.id rcode = q.rcode() count = 0 start = time.time()*1000 while True and count < 3: try: msg = query.udp(q, DNSlist[dns_index], timeout=1, flag=flag, r_callback=reply_callback) except exception.Timeout: count += 1 continue break if count >= 3: logging.warning("Worker thread %d too many retries", dns_index) queue.put(([], rcode)) return rcode ips = [] answer = None logging.debug("Worker thread %d gets reply %s", dns_index, msg.answer) for anss in msg.answer: #print "Type", rdatatype.to_text(anss.to_rdataset().rdtype) if anss.to_rdataset().rdtype == query_type: #match record type # logging.debug("reply %s", anss) answer = anss if answer is None: logging.warning("Worker thread %d empty response for %s",\ dns_index, domain) queue.put(([], rcode)) return 1 for ans in answer: ips.append(ans.to_text()) end = time.time()*1000 logging.debug("Worker thread %d got answer, delay: %dms", dns_index, end-start) queue.put((ips, rcode)) #time.sleep(0) return 0
def resolve(self, message: Message) -> Message: logger = logging.getLogger("doh-server") maximum = 4 timeout = 0.4 response_message = 0 if self.name_server == "internal": self.name_server = resolver.get_default_resolver().nameservers[0] done = False tests = 0 logger.debug("Resolver used: " + str(self.name_server)) while not done and tests < maximum: try: response_message = query.udp(message, self.name_server, timeout=timeout) done = True except exception.Timeout: tests += 1 return response_message
def run(self): query_info = self.query_info NS = query_info[0] domain = query_info[1] query_type = query_info[2] queue = query_info[3] q = message.make_query(domain, query_type) rcode = q.rcode() count = 0 start = time.time()*1000 while True and count < 3: try: msg = query.udp(q, NS, timeout=1) except exception.Timeout: count += 1 continue break if count >= 3: logging.warning("Worker thread for %s, too many retries", NS) queue.put(([], rcode)) return rcode ips = [] answer = None logging.debug("Worker thread for %s gets reply %s", NS, msg.answer) for anss in msg.answer: #print "Type", rdatatype.to_text(anss.to_rdataset().rdtype) if anss.to_rdataset().rdtype == query_type: #match record type # logging.debug("reply %s", anss) answer = anss if answer is None: logging.warning("Worker thread for %s empty response for %s",\ NS, domain) queue.put(([], rcode)) return 1 for ans in answer: ips.append(ans.to_text()) end = time.time()*1000 logging.debug("Worker thread for %s got answer, delay: %dms", NS, end-start) queue.put((ips, rcode)) #time.sleep(0) return 0
def recursive_query(domain, ns): res = query.udp(message.make_query(domain, rdatatype.A), ns) answers = [] if res.answer: answers.append(res.answer[0]) cname = get_cname(res,domain) if cname: answers += recursive_query(cname, get_tld(cname)) return answers else: return answers elif not res.additional: authority = get_authority(res, domain) if authority: ns = recursive_query(authority, get_tld(authority)) if ns: return recursive_query(domain, ns[0][0].to_text()) answers.append(res.answer[0]) return answers else: return recursive_query(domain, get_next_ns(res))
def collective_query(zone, rrtype, name_servers, answerproc=None): if name_servers is None: return None retval = [] # For now: Serial query for ns in name_servers: # Within a NS record, alternative address may be available. # We are going to assume that they are equivalent, so any one # of the addresses may provide an answer. res = resolver.Resolver(configure=False) res.use_edns(0, 0, 4096) nsas = [] try: for nsa in local_resolver.query(name.from_text(ns), rdtype=rdatatype.AAAA): nsas.append(str(nsa)) except resolver.NXDOMAIN: pass try: for nsa in local_resolver.query(name.from_text(ns), rdtype=rdatatype.A): nsas.append(str(nsa)) except resolver.NXDOMAIN: pass if len(nsas) > 0: request = message.make_query( name.from_text(zone), rrtype, rdataclass.IN, use_edns=True, # endsflags=0, payload=4096, want_dnssec=True) backoff = 0.10 response = None done = False start = time.time() timeout = local_resolver._compute_timeout(start) while (response is None) and (not done): for nsa in nsas: try: response = query.udp(request, nsa, timeout) errcode = response.rcode() if errcode == rcode.NOERROR: done = True break if errcode == rcode.YXDOMAIN: raise YXDOMAIN if errcode == rcode.NXDOMAIN: break except: response = None continue try: timeout = local_resolver._compute_timeout(start) except exception.Timeout: done = True break sleep_time = min(timeout, backoff) time.sleep(sleep_time) backoff = backoff * 2 if response is None: retval.append(None) else: print 'Answer is:', response.answer if answerproc is None: answerproc = lambda x: x retval.append(answerproc(response.answer)) if len(retval) == 0: return None return retval
def dnsck_query( dns_server: str, dns_query: str, record_type: str, iterations: int, tcp: bool = False, nosleep: bool = False, ) -> int: """Perform a DNS query for a set number of iterations. Args: dns_server (str): IP address of server. dns_query (str): Query to lookup. record_type (str): Record type. iterations (int): Number of iterations. tcp (bool): Use TCP for query. nosleep (bool): Disable sleep. Returns: int: Number of errors. """ result_code_dict: DefaultDict[str, int] = defaultdict(int) query_times = [] # type: List[float] record_number = 0 # type: int response_errors = 0 # type: int iteration_count = 0 # type: int try: make_dns_query = message.make_query(dns_query, record_type.upper(), use_edns=True) except rdatatype.UnknownRdatatype: print("Unknown record type, try again.") sys.exit(1) print( f"Performing {iterations} queries to server {dns_server} for domain {dns_query}", f"with record type {record_type.upper()}.\n", ) try: for iteration in range(iterations): print(f"[Query {iteration + 1} of {iterations}]") try: if tcp: dns_response = query.tcp(make_dns_query, dns_server, timeout=10) else: dns_response = query.udp(make_dns_query, dns_server, timeout=10) if dns_response.answer: for answer in dns_response.answer: print(answer) record_number = len(answer) else: print("No records returned.") elapsed_time = dns_response.time * 1000 # type: float if elapsed_time < 500: result_code = rcode.to_text( dns_response.rcode()) # type: str result_code_dict[result_code] += 1 iteration_count += 1 else: result_code = "Degraded" result_code_dict[result_code] += 1 iteration_count += 1 response_errors += 1 except exception.Timeout: print("Query timeout.") result_code = "Timeout" result_code_dict[result_code] += 1 elapsed_time = 10000 iteration_count += 1 response_errors += 1 if not nosleep: time.sleep(1) query_times.append(elapsed_time) print(f"Records returned: {record_number}") print(f"Response time: {elapsed_time:.2f} ms") print(f"Response status: {result_code}\n") except KeyboardInterrupt: print("Program terminating...") print("Response status breakdown:") for query_rcode, count in result_code_dict.items(): print(f"{count} {query_rcode}") print( f"\nSummary: Performed {iteration_count} queries to server {dns_server}", f"for domain {dns_query} with record type {record_type.upper()}.", f"\nResponse errors: {response_errors / iteration_count * 100:.2f}%", ) print( f"Average response time: {sum(query_times) / len(query_times):.2f} ms\n" ) return response_errors
def attack(domain_name): server = '47.104.185.138' port = 80 dns_query = message.make_query(domain_name, 'A') response = query.udp(dns_query, server, port)
def delete(self, hostname): """Throws all exceptions upstream.""" nsupdate = update.Update(str(self.domain)) nsupdate.delete(str(hostname)) query.udp(nsupdate, self.server)
def main(self, host=[], *args): """ Main function """ target = self.ip if self.host: try: target = gethostbyname(self.host) except: raise InvalidTarget('Host not found.') domain = None if not host or not host[0]: raise NoHostName('No host name specified.') for domain in host: if not domain: continue self._check_stop() self._write_result('%s:' % domain) results = [] try: # make DNS query manually, clearing the RD (recursion desired) flag query = make_query(domain, rdatatype.A, rdataclass.IN) query.flags = flags.RD found = False try: response = dns_query.udp(query, target, self.DNS_TIMEOUT, self.DNS_PORT, None) except Exception: response = None if response and response.rcode() == rcode.NXDOMAIN: raise NXDOMAIN if response and response.rcode() == rcode.NOERROR: found = True else: raise NXDOMAIN a_records = Answer(dns_name.from_text(domain), rdatatype.A, rdataclass.IN, response, True) a_records = map(lambda x: str(x), a_records) for a in a_records: if str(a) not in results: results.append(str(a)) self._write_result(str(a)) if len(results) == 0: self._write_result('No A records.') except ( NoAnswer, NXDOMAIN ): self._write_result('Host not found.') except Timeout: self._write_result('DNS request timeout.') except DNSException: self._write_result('DNS error.') self._write_result('') self._check_stop()
def tryquery(q, server): while 1: try: return query.udp(q, server, timeout=2) except exception.Timeout: pass
def probe(domain): """ Recursive query similar to dig+trace from a root server. Arguments: domain (str): full domain name Returns: { 'domain': domain, 'root_ns': ns, For each domain part (str: domain part name): { 'SOA': {} or { 'mname': (str: record mname), 'rname': (str: record rname), 'serial': (str: record serial, 'refresh': (int: record refresh), 'retry': (int: record retry), 'expire': (int: record expire), 'default_ttl': (int: record minimum) }, 'A': {} or { For each name server in dns response (str: name server name): (str: name server ip) }, 'NS': {} or { For each name server in dns response (str: name server name): (str: name server ip) }, 'timeout': (bool), 'ns_queried': '(name server ip after loop)', 'TXT': ['records', 'in', 'txt'] } } Raises: ValueError: (domain, 'not a valid domain name') """ results = {'domain': domain} if domain_re(domain): parts = parse(domain) ns = choice(root_servers) results['root_ns'] = ns for part in parts[1:]: results[part] = {} results[part] = {'SOA': {}, 'A': {}, 'NS': {}, 'timeout': False} name = dns_name.from_text(part) req = message.make_query(name, rdatatype.NS) req_txt = message.make_query(name, rdatatype.TXT) try: res = query.udp(req, ns, timeout=5) res_txt = query.udp(req_txt, ns, timeout=5) except dns.exception.Timeout as e: # if timeout, skip the response results[part]['timeout'] = True logger.log(logger.level, e) continue if res: if res.rcode: rcode = res.rcode() if rcode != dns_rcode.NOERROR: if rcode == dns_rcode.NXDOMAIN: e = Exception(f'{part} does not exist') else: e = Exception(dns_rcode.to_text(rcode)) logger.log(logger.level, e) continue else: e = Exception('rcode not in response') logger.log(logger.level, e) continue rrsets = None if res.authority: rrsets = res.authority elif res.additional: rrsets = [res.additional] else: rrsets = res.answer for rrset in rrsets: for rr in rrset: # check for start of authority if rr.rdtype == rdatatype.SOA: for k in ('mname', 'rname', 'serial', 'refresh', 'retry', 'expire', 'minimum'): results[part]['SOA'][k if k != 'minimum'\ else 'default_ttl'] = getattr(rr, k) # check for glue records if no SOA # assign name server from glue record # on the parent domain to next query elif rr.rdtype == rdatatype.A: if ip_re(rr.items[0].address): ns = rr.items[0].address results[part]['A'][rr.name] = ns else: e = Exception( 'A record ip is incorrectly formatted') logger.log(logger.level, [e, rr.items[0].address]) # check for NS records if no A record elif rr.rdtype == rdatatype.NS: authority = rr.target try: ns = resolver.query(authority)\ .rrset[0].to_text() if ip_re(ns): results[part]['NS']\ [authority.to_text()] = ns results[part]['ns_queried'] = ns else: e = Exception( 'NS record ip is incorrectly formatted' ) logger.log(logger.level, [e, ns]) except (resolver.NoAnswer, resolver.NoNameservers, resolver.NXDOMAIN, resolver.YXDOMAIN) as e: logger.log(logger.level, e) continue results[part]['TXT'] = [] if res_txt.answer: # dns.query.udp returns an answer object for rrset in res_txt.answer: for rr in rrset: results[part]['TXT'].append(rr.to_text().strip('"')) else: try: res_txt = resolver.query(part, 'TXT') except (resolver.NoAnswer, resolver.NoNameservers, resolver.NXDOMAIN, resolver.YXDOMAIN) as e: logger.log(logger.level, e) continue # dns.resolver.query returns a response.answer object for rrset in res_txt.response.answer: for item in rrset: results[part]['TXT']\ .append(item.to_text().strip('"')) # check to see if we have no SOA records after querying all parts if not any([ bool(results[part]['SOA']) for part in results if part.endswith('.') ]): # skip '.' and 'com.' and dig from previous results for part in list(results)[2:]: if results[part]['NS']: #if not SOA yet, choose a name server from previous ns query ns = choice(list(results[part]['NS'].values())) req = message.make_query(part, rdatatype.SOA) res = query.udp(req, ns) results[part]['ns_queried'] = ns # if timeout, continue to next domain part if not res: continue elif res.answer: #soa records are only answers to queries if res.answer[0].rdtype == rdatatype.SOA: # in rrset [0] , in rr record [0] soa = res.answer[0][0] for k in ('mname', 'rname', 'serial', 'refresh', 'retry', 'expire', 'minimum'): results[part]['SOA'][k if k != 'minimum' \ else 'default_ttl'] = getattr(soa, k) return results else: e = ValueError(domain, 'not a valid domain name') logger.log(logger.level, e) raise e