def lookup_dns(self, domain): if not self.discoverNS: DNS.DiscoverNameServers() self.discoverNS = True name = '_dmarc.' + domain try: req = DNS.DnsRequest(name=name, qtype=DNS.Type.TXT, timeout=self.dnstimeout) res = req.req() if res.header['tc'] == True: try: req = DNS.DnsRequest(name, qtype='TXT', protocol='tcp', timeout=self.dnstimeout) res = req.req() except DNS.DNSError as x: print('DNS: TCP fallback error:', str(x)) if res.header['rcode'] != 0 and res.header['rcode'] != 3: print('DNS Error:', res.header['status'], ' RCODE ({})'.format(res.header['rcode'])) return [((a['name'], a['typename']), a['data']) for a in res.answers] \ + [((a['name'], a['typename']), a['data']) for a in res.additional] except AttributeError as x: print('DNS attribute:' + str(x)) except IOError as x: print('DNS IOE:' + str(x)) except DNS.DNSError as x: 'DNS ' + str(x)
def DNSLookup(name, qtype, strict=True, timeout=30): try: req = DNS.DnsRequest(name, qtype=qtype, timeout=timeout) resp = req.req() # resp.show() # key k: ('wayforward.net', 'A'), value v # FIXME: pydns returns AAAA RR as 16 byte binary string, but # A RR as dotted quad. For consistency, this driver should # return both as binary string. # if resp.header['tc'] == True: if strict > 1: raise spf.AmbiguityWarning( 'DNS: Truncated UDP Reply, SPF records should fit in a UDP packet, retrying TCP' ) try: req = DNS.DnsRequest(name, qtype=qtype, protocol='tcp', timeout=timeout) resp = req.req() except DNS.DNSError as x: raise spf.TempError('DNS: TCP Fallback error: ' + str(x)) return [((a['name'], a['typename']), a['data']) for a in resp.answers] except IOError as x: raise spf.TempError('DNS ' + str(x)) except DNS.DNSError as x: raise spf.TempError('DNS ' + str(x))
def testIDND(self): """Can we lookup an internationalized domain name?""" dnsob = DNS.DnsRequest('xn--bb-eka.at') unidnsob = DNS.DnsRequest('öbb.at') a_resp = dnsob.req(qtype='A', resulttype='text') ua_resp = unidnsob.req(qtype='A', resulttype='text') self.assertTrue(a_resp.answers) self.assertTrue(ua_resp.answers) self.assertEqual(ua_resp.answers[0]['data'], a_resp.answers[0]['data'])
def __init__(self, dnsServer=None, cachefile=""): # These attributes intended for user setting self.printStatsAtEnd = False # As far as I can tell from the standards, # it's legal to have more than one PTR record # for an address. That is, it's legal to get # more than one name back when you do a # reverse lookup on an IP address. I don't # know of a use for that and I've never seen # it done. And I don't think that most # people would expect it. So forward ("A") # lookups always return a list. Reverse # ("PTR") lookups return a single name unless # this attribute is set to False. self.returnSinglePTR = True # How long to cache an error as no data self.cacheErrorSecs = 5 * 60 # How long to wait for the server self.dnsTimeout = 10 # end of user-settable attributes self.cachefile = os.path.expanduser(cachefile) self.caches = None if self.cachefile and os.path.exists(self.cachefile): try: self.caches = pickle_read(self.cachefile) except: os.unlink(self.cachefile) if self.caches is None: self.caches = {"A": {}, "PTR": {}} if options["globals", "verbose"]: if self.caches["A"] or self.caches["PTR"]: print >> sys.stderr, "opened existing cache with", print >> sys.stderr, len(self.caches["A"]), "A records", print >> sys.stderr, "and", len(self.caches["PTR"]), print >> sys.stderr, "PTR records" else: print >> sys.stderr, "opened new cache" self.hits = 0 # These two for statistics self.misses = 0 self.pruneTicker = 0 if dnsServer == None: DNS.DiscoverNameServers() self.queryObj = DNS.DnsRequest() else: self.queryObj = DNS.DnsRequest(server=dnsServer) return None
def testDNSRequestTXTD(self): dnsob = DNS.DnsRequest('fail.kitterman.org') respdef = dnsob.req(qtype='TXT') self.assertTrue(respdef.answers) data = respdef.answers[0]['data'] self.assertEqual(data, [b'v=spf1 -all'])
def is_gooddomain(host): a = DNS.DnsRequest(host, qtype='a').req().answers for record in a: if record['typename'] == "A": return record['data'] return
def lookup(self, record="A"): if globalvars.verbose: mydns = ", ".join(self.dns_servers) self.equeue.put("Looking up %s with %s\n" % (self.hostname, mydns)) try: ipaddress = None for svr in self.dns_servers: # We set a short timeout because life moves too fast...so does the game! r = DNS.DnsRequest(self.hostname, qtype="A", server=[svr], protocol='udp', timeout=60) res = r.req() for answer in res.answers: if answer["data"]: ipaddress = answer["data"] break else: self.equeue.put("Failed to get DNS!") if ipaddress: if ctfnet_re.search(ipaddress): if globalvars.verbose: self.equeue.put("got %s\n" % self.ipaddress) self.ipaddress = ipaddress return True else: self.equeue.put("Got non RFC1918: %s\n" % ipaddress) return False else: return False except: traceback.print_exc(file=self.equeue) self.ipaddress = None return False
def lookup(self, IP=None, name=None): import DNS now = time.time() if (not IP) and (not name): return None if IP: if type(IP) != type(''): return None a = string.split(IP, '.') a.reverse() name = string.join(a, '.') + '.in-addr.arpa' cache = self.revCache qt = 'ptr' else: if type(name) != type(''): return None cache = self.forCache qt = 'a' if name in cache: # Check if it's timed out or not if cache[name][1] < now: del (cache[name]) else: return (cache[name][0]) x = DNS.DnsRequest(name, qtype=qt) try: x.req() except: return 'Timeout' if len(x.response.answers) > 0: cache[name] = (x.response.answers[0]['data'], x.time_finish + x.response.answers[0]['ttl']) else: cache[name] = (None, now + self.negCache) return cache[name][0]
def __get_remote_current_version(self): """ Retrieve last info about database return dictionary that contains engine, main and daily current version, else None """ # automatically load nameserver(s) from /etc/resolv.conf # (works on unix - not on windows conf = self.__resolv_conf_for_win() DNS.ParseResolvConf(conf) self.__del_file(conf) dns_request = DNS.DnsRequest(name='current.cvd.clamav.net', qtype='TXT') dns_answer = dns_request.req() if not dns_answer: return CL_Py_DNS_Error all_info = dns_answer.answers[0] raw = str(all_info["data"][0]) raw_split = raw.split(':') current_version = dict() current_version["engine"] = raw_split[0] current_version["main"] = atoi(raw_split[1]) current_version["daily"] = atoi(raw_split[2]) return current_version
def testDnsRequestAAAA(self): import ipaddress dnsobj = DNS.DnsRequest('example.org') aaaa_response = dnsobj.qry(qtype='AAAA', resulttype='text') self.assertTrue(aaaa_response.answers) # does the result look like an ipv6 address? self.assertTrue(':' in aaaa_response.answers[0]['data']) self.assertEqual(aaaa_response.answers[0]['data'], '2606:2800:220:6d:26bf:1447:1097:aa7') # default is returning ipaddress object aaaad_response = dnsobj.qry(qtype='AAAA') self.assertTrue(aaaad_response.answers) self.assertEqual( aaaad_response.answers[0]['data'], ipaddress.IPv6Address('2606:2800:220:6d:26bf:1447:1097:aa7')) aaaab_response = dnsobj.qry(qtype='AAAA', resulttype='binary') self.assertTrue(aaaab_response.answers) # is it ipv6 looking? self.assertEqual(len(aaaab_response.answers[0]['data']), 16) for b in aaaab_response.answers[0]['data']: assertIsByte(b) self.assertEqual(aaaab_response.answers[0]['data'], b'&\x06(\x00\x02 \x00m&\xbf\x14G\x10\x97\n\xa7') # IPv6 decimal aaaai_response = dnsobj.qry(qtype='AAAA', resulttype='integer') self.assertTrue(aaaai_response.answers) self.assertEqual(aaaai_response.answers[0]['data'], 50542628918019815862290244053507705511)
def main(): import DNS, timing, socket, time res = {} for server in servers: res[server] = [100000, 0, 0, 0] # min,max,tot,failed for what, querytype in lookups: for count in range(rpts): for server in servers: d = DNS.DnsRequest(server=server, timeout=1) fail = 0 timing.start() try: r = d.req(name=what, qtype=querytype) except DNS.Error: fail = 1 timing.finish() if fail: res[server][3] = res[server][3] + 1 print "(failed)", res[server][3] if 0: if r.header['ancount'] == 0: print "WARNING: Server",server,"got no answers for", \ what, querytype t = timing.milli() print server, "took", t, "ms for", what, querytype res[server][0] = min(t, res[server][0]) res[server][1] = max(t, res[server][1]) res[server][2] = res[server][2] + t for server in servers: queries = rpts * len(lookups) r = res[server] print "%-30s %2d/%2d(%3.2f%%) %dms/%dms/%dms min/avg/max" % ( socket.gethostbyaddr(server)[0], queries - r[3], queries, ((queries - r[3]) * 100.0) / queries, r[0], r[2] / queries, r[1])
def testDnsRequestA(self): # try with asking for strings, and asking for bytes dnsobj = DNS.DnsRequest('example.org') a_response = dnsobj.qry(qtype='A', resulttype='text') self.assertTrue(a_response.answers) # is the result vaguely ipv4 like? self.assertEqual(a_response.answers[0]['data'].count('.'), 3) self.assertEqual(a_response.answers[0]['data'], '93.184.216.119') # Default result type for .qry object is an ipaddress object ad_response = dnsobj.qry(qtype='A') self.assertTrue(ad_response.answers) self.assertEqual(ad_response.answers[0]['data'], ipaddress.IPv4Address('93.184.216.119')) ab_response = dnsobj.qry(qtype='A', resulttype='binary') self.assertTrue(ab_response.answers) # is the result ipv4 binary like? self.assertEqual(len(ab_response.answers[0]['data']), 4) for b in ab_response.answers[0]['data']: assertIsByte(b) self.assertEqual(ab_response.answers[0]['data'], b']\xb8\xd8w') ai_response = dnsobj.qry(qtype='A', resulttype='integer') self.assertTrue(ai_response.answers) self.assertEqual(ai_response.answers[0]['data'], 1572395127)
def DNSResolve(s): if DNS: DNS.ParseResolvConf() # Windows? r = DNS.DnsRequest(name=s, qtype='A') a = r.req() return a.answers[0]['data'] else: return socket.gethostbyname(s)
def wan_ip(): """ Return the WAN IP of the host running this script. """ DNS.defaults['server'] = ('resolver1.opendns.com', 'resolver2.opendns.com', 'resolver3.opendns.com', 'resolver4.opendns.com') res = DNS.DnsRequest('myip.opendns.com').qry() return res.answers[0]['data']
def test_email_converter(value, state=None): if value is None: return value, None if state is None: state = states.default_state username, domain = value.split('@', 1) try: # For an email domain to be considered valid, either A or MX request should work (both are not needed). answers = DNS.DnsRequest(domain, qtype='a', timeout=10).req().answers if not answers: answers = DNS.DnsRequest(domain, qtype='mx', timeout=10).req().answers except (socket.error, DNS.DNSError), e: return value, state._( u'An error occured when trying to connect to the email server: {0}' ).format(e)
def testDnsRequestAD(self): # try with asking for strings, and asking for bytes dnsob = DNS.DnsRequest('example.org') ad_response = dnsob.req(qtype='A') self.assertTrue(ad_response.answers) # is the result vaguely ipv4 like? self.assertEqual(ad_response.answers[0]['data'].count('.'), 3) self.assertEqual(ad_response.answers[0]['data'], '93.184.216.119')
def testDnsRequestMX(self): dnsobj = DNS.DnsRequest('ietf.org') mx_response = dnsobj.qry(qtype='MX') self.assertTrue(mx_response.answers[0]) # is hard coding a remote address a good idea? # I think it's unavoidable. - sk self.assertEqual(mx_response.answers[0]['data'], (0, 'mail.ietf.org')) m = DNS.mxlookup('ietf.org') self.assertEqual(mx_response.answers[0]['data'], m[0])
def lookup(query, type='a'): """ Lookup DNS entries of specified type. >>> lookup('localhost') ['127.0.0.1'] """ rr = DNS.DnsRequest(query, qtype=type).req().answers result = map(lambda x: x['data'], rr) return result
def DNSLookup(name, qtype): try: req = DNS.DnsRequest(name, qtype=qtype) resp = req.req() #resp.show() # key k: ('wayforward.net', 'A'), value v return [((a['name'], a['typename']), a['data']) for a in resp.answers] except IOError: raise TempError, 'DNS ' + str(x) except DNS.DNSError, x: raise TempError, 'DNS ' + str(x)
def testNSD(self): """Lookup NS record from SOA""" dnsob = DNS.DnsRequest('kitterman.com') resp = dnsob.req(qtype='SOA') self.assertTrue(resp.answers) primary = resp.answers[0]['data'][0] self.assertEqual(primary, 'ns1.pairnic.com') resp = dnsob.req(qtype='NS', server=primary, aa=1) nslist = [x['data'].lower() for x in resp.answers] nslist.sort() self.assertEqual(nslist, ['ns1.pairnic.com', 'ns2.pairnic.com'])
def get_dbservername(domainname): '''Datenbankserver ermitteln''' log('get dbservername for ' + domainname) DNS.DiscoverNameServers() dbsrvname = None try: dbsrvname = map(lambda x: x['data'], DNS.DnsRequest('_pkgdb._tcp.' + domainname, qtype='srv').req().answers)[0][3] except: log('Cannot find service-record of _pkgdb._tcp.') print('Cannot find service-record of _pkgdb._tcp.') return dbsrvname
def dns_resolver(self, domain): """ dns resolver """ try: import DNS req = DNS.DnsRequest(domain, qtype='A').req().answers return [r['data'] for r in req if r['typename'] == 'A'] except: self.logger.error(grac_format_exc()) return []
def testDnsRequestAAAAD(self): dnsob = DNS.DnsRequest('example.org') # default is returning binary instead of text aaaad_response = dnsob.req(qtype='AAAA') self.assertTrue(aaaad_response.answers) # does the result look like a binary ipv6 address? self.assertEqual(len(aaaad_response.answers[0]['data']), 16) for b in aaaad_response.answers[0]['data']: assertIsByte(b) self.assertEqual(aaaad_response.answers[0]['data'], b'&\x06(\x00\x02 \x00m&\xbf\x14G\x10\x97\n\xa7')
def f(value): try: username, domain = value.split('@', 1) except ValueError: raise Invalid(_msg(f.msg, 'email.format', 'invalid format')) if not _usernameRE.match(username): raise Invalid(_msg(f.msg, 'email.username', 'invalid username')) if not _domainRE.match(domain): raise Invalid(_msg(f.msg, 'email.domain', 'invalid domain')) if f.check_dns: try: a = DNS.DnsRequest(domain, qtype='mx').req().answers if not a: a = DNS.DnsRequest(domain, qtype='a').req().answers dnsdomains = [x['data'] for x in a] except (socket.error, DNS.DNSError), e: raise Invalid(_msg(f.msg, 'email.socket_error', 'socket error')) if not dnsdomains: raise Invalid( _msg(f.msg, 'email.domain_error', 'no such domain'))
def getQtypeAnswers(name, type, server, protocol='udp', times=1): success = 0 try: r = DNS.DnsRequest(name=name, qtype=type, server=server, protocol=protocol, timeout=1) answerslist = r.req() # while answerslist.header['ancount'] == 0 : # times = times + 1 # answerslist = getQtypeAnswers(name,type,server,protocol,times) return answerslist except: # print "Timeout",name,type,server # logging.error(("Timeout 5 times",name,type,server)) return 0
def is_using_tor(client_ip, el_port='80'): ''' Find out if clientIp is a tor exit node following query type one. Inspired by https://svn.torproject.org/svn/check/trunk/cgi-bin/TorCheck.py Query Specification under https://gitweb.torproject.org/tordnsel.git/blob/HEAD:/doc/torel-design.txt See also https://check.torproject.org/ ''' DNS.DiscoverNameServers() # Put user ip in right format split_ip = client_ip.split('.') split_ip.reverse() el_exit_node = '.'.join(split_ip) # get beam's current ip address name = settings.ENV_SITE_MAPPING[settings.ENV][settings.SITE_USER] el_target = DNS.dnslookup(name, 'A') # ExitList DNS server we want to query el_host = 'ip-port.exitlist.torproject.org' # Prepare the question as an A record (i.e. a 32-bit IPv4 address) request el_question = el_exit_node + "." + el_port + "." + el_target[ 1] + "." + el_host request = DNS.DnsRequest(name=el_question, qtype='A', timeout=settings.TOR_TIMEOUT) # Ask the question and load the data into our answer try: answer = request.req() except DNS.DNSError as e: log_error('ERROR Tor - Failed to query ip address: {}'.format(e[0])) return False # Parse the answer and decide if it's allowing exits # 127.0.0.2 is an exit and NXDOMAIN is not if answer.header['status'] == 'NXDOMAIN': return False else: # unexpected response if not answer.answers: log_error('ERROR Tor - Query returned unexpected response') return False for a in answer.answers: if a['data'] != '127.0.0.2': return False return True
def dns_reverse_lookup(dns_server, timeout_in_sec, ip, logger): '''Tries to return a hostname doing a DNS rev lookup''' dns_answered = False try: reversed_ip = '.'.join(ip.split('.')[::-1]) except Exception as e: logger.critical('not a valid IP') logger.critical(e) sys.exit(FAILURE_CONSTANT) try: dns_obj = DNS.DnsRequest(server=dns_server, timeout=timeout_in_sec) except Exception, error: logger.critical('failed to talk to DNS NS') logger.critical(e) sys.exit(FAILURE_CONSTANT)
def DNSLookup(name, qtype): try: # To be thread safe, we create a fresh DnsRequest with # each call. It would be more efficient to reuse # a req object stored in a Session. req = DNS.DnsRequest(name, qtype=qtype) resp = req.req() #resp.show() # key k: ('wayforward.net', 'A'), value v # FIXME: pydns returns AAAA RR as 16 byte binary string, but # A RR as dotted quad. For consistency, this driver should # return both as binary string. return [((a['name'], a['typename']), a['data']) for a in resp.answers] except IOError as x: raise DNSError(str(x))
def testDNSRequestTXT(self): dnsobj = DNS.DnsRequest('fail.kitterman.org') respdef = dnsobj.qry(qtype='TXT') self.assertTrue(respdef.answers) data = respdef.answers[0]['data'] self.assertEqual(data, [b'v=spf1 -all']) resptext = dnsobj.qry(qtype='TXT', resulttype='text') self.assertTrue(resptext.answers) data = resptext.answers[0]['data'] self.assertEqual(data, ['v=spf1 -all']) respbin = dnsobj.qry(qtype='TXT', resulttype='binary') self.assertTrue(respbin.answers) data = respbin.answers[0]['data'] self.assertEqual(data, [b'\x0bv=spf1 -all'])
def _get_mx1(self, domain): if domain in ('localhost', ): return None import DNS # FIXME: This bypasses the connection broker and is not secured or # anonymized. DNS.DiscoverNameServers() try: timeout = (self.deadline - time.time()) // 2 mxlist = DNS.DnsRequest(name=domain, qtype=DNS.Type.MX, timeout=timeout).req() mxs = sorted([m['data'] for m in mxlist.answers if 'data' in m]) return mxs[0][1] if mxs else None except socket.error: return None