예제 #1
0
    def main(self, min_len=(1, ), max_len=(3, )):
        """
        Main function
        """
        try:
            min_len = int(min_len[0])
            max_len = int(max_len[0])
        except TypeError:
            self._write_result("Min and max length should be integer values.")
            return

        if min_len > max_len or min_len <= 0:
            self._write_result(
                "Min length should be greater than 0 and less or equal to max length."
            )
            return

        if not self.host:
            return

        if self.host.startswith("www."):
            self.host = self.host[4:]

        # collect nameservers
        r = Resolver()
        r.lifetime = self.DNS_TIMEOUT

        name_servers = r.query(self.host, "NS")
        name_servers = map(lambda x: str(x), name_servers)

        ns_list = []

        for name_server in name_servers:
            if name_server[-1] == ".":
                name_server = name_server[:-1]

            ns_list.append(gethostbyname(name_server))

        r = Resolver()
        r.lifetime = self.DNS_TIMEOUT
        r.nameservers = ns_list

        results = set()

        for sub in self.generate_subdomains(min_len, max_len):
            domain = "%s.%s" % (sub, self.host)

            for record in ("A", "CNAME"):
                try:
                    records = r.query(domain, record)

                    if records:
                        if sub not in results:
                            results.add(sub)
                            self._write_result(domain)

                        break

                except Exception:
                    pass
예제 #2
0
def reverse_dns_lookup(input, timeout=3, server=""):
    """Perform a simple reverse DNS lookup, return results in a dictionary"""
    assert _REVERSE_DNS_REGEX.search(
        input), "Invalid address format: '{0}'".format(input)
    resolver = Resolver()
    resolver.timeout = float(timeout)
    resolver.lifetime = float(timeout)
    if server:
        resolver.nameservers = [server]
    try:
        tmp = input.strip().split(".")
        tmp.reverse()
        inaddr = ".".join(tmp) + ".in-addr.arpa"
        records = resolver.query(inaddr, "PTR")
        return {
            "name": records[0].to_text(),
            "lookup": inaddr,
            "error": "",
            "addr": input,
        }
    except DNSException as e:
        return {
            "addrs": [],
            "lookup": inaddr,
            "error": repr(e),
            "name": input,
        }
예제 #3
0
def check_dns(check):
    # Setup the resolver
    resolver = Resolver()
    resolver.nameservers = [check.config['HOST']]
    resolver.timeout = dns_config['timeout']
    resolver.lifetime = dns_config['lifetime']

    # Query resolver
    check.add_output('Querying {HOST} for "{LOOKUP}"...', **check.config)
    lookup = resolver.query(check.config['LOOKUP'], check.config['TYPE'])

    found = False
    for ans in lookup:
        if str(ans) == check.config['EXPECTED']:
            found = True
        else:
            check.addOutput('NOTICE: DNS Server returned {}', ans)

    if not found:
        check.addOutput(
            'ERROR: DNS Server did not respond with the correct IP')
        return False

    # We're good!
    return True
예제 #4
0
파일: TakeOver.py 프로젝트: gfek/Lepus
def takeOver(domain):
    A = []
    CNAME = []
    results = []
    resolver = Resolver()
    resolver.timeout = 1
    resolver.lifetime = 1
    types = ["A", "CNAME"]

    for type in types:
        try:
            answers = resolver.query(domain, type)

            for answer in answers:
                if type == "A":
                    A.append(answer.address)

                if type == "CNAME":
                    CNAME.append(answer.target)

        except (NXDOMAIN, NoAnswer, EmptyLabel, NoNameservers, Timeout,
                DNSException):
            pass

        except Exception:
            return None

    results = identify(domain, A, CNAME)
    return results
예제 #5
0
파일: TakeOver.py 프로젝트: gfek/Lepus
def smugmug(domain, ARecords, CNAME):
    outcome = []

    try:
        if get("http://" + domain, headers=headers).status_code == 404:
            outcome = ["Smugmug", domain, CNAME]
            return outcome

    except Exception:
        pass

    try:
        if get("https://" + domain, headers=headers,
               verify=False).status_code == 404:
            outcome = ["Smugmug", domain, CNAME]
            return outcome

    except Exception:
        pass

    resolver = Resolver()
    resolver.timeout = 1
    resolver.lifetime = 1

    try:
        resolver.query(CNAME)

    except NXDOMAIN:
        outcome = ["Smugmug", domain, CNAME]

    return outcome
예제 #6
0
 def cname(self, dom: Domain, timeout: int) -> List[int]:
     """Collect CNAME records on domain."""
     # List of domains to check
     dom_list = [dom.url, "www." + dom.url]
     # Our codes to return
     return_code = []
     # Seutp resolver and timeouts
     resolver = Resolver()
     resolver.timeout = timeout
     resolver.lifetime = LIFETIME
     cname_query = resolver.query
     # Iterate through all domains in list
     for domain in dom_list:
         try:
             response = cname_query(domain, "cname")
             dom.cnames = [record.to_text() for record in response]
         except NoAnswer:
             return_code.append(1)
         except NoNameservers:
             return_code.append(2)
         except NXDOMAIN:
             return_code.append(3)
         except Timeout:
             return_code.append(4)
     return return_code
예제 #7
0
    def dns(self, name, qtype):
        """DNS query.

        If the result is in cache, return that.  Otherwise pull the
        result from DNS, and cache ALL answers, so additional info
        is available for further queries later.

        CNAMEs are followed.

        If there is no data, [] is returned.

        pre: qtype in ['A', 'AAAA', 'MX', 'PTR', 'TXT', 'SPF']
        post: isinstance(__return__, types.ListType)
        """
        result = self.cache.get( (name, qtype) )
        cname = None
        if not result:
            req  = Resolver()
            req.lifetime = self.timeout
            resp = req.query(name, qtype)
            for a in resp:
                # key k: ('wayforward.net', 'A'), value v
                k, v = (name, qtype), a
                if k == (name, 'CNAME'):
                    cname = v
                self.cache.setdefault(k, []).append(v)
            result = self.cache.get( (name, qtype), [])
        if not result and cname:
            result = self.dns(cname, qtype)
        return result
예제 #8
0
def reverse_dns_lookup(input, timeout=3, server=''):
    """Perform a simple reverse DNS lookup, return results in a dictionary"""
    assert _REVERSE_DNS_REGEX.search(
        input), "Invalid address format: '{0}'".format(input)
    resolver = Resolver()
    resolver.timeout = float(timeout)
    resolver.lifetime = float(timeout)
    if server:
        resolver.nameservers = [server]
    try:
        tmp = input.strip().split('.')
        tmp.reverse()
        inaddr = '.'.join(tmp) + ".in-addr.arpa"
        records = resolver.query(inaddr, 'PTR')
        return {
            'name': records[0].to_text(),
            'lookup': inaddr,
            'error': '',
            'addr': input,
        }
    except DNSException as e:
        return {
            'addrs': [],
            'lookup': inaddr,
            'error': repr(e),
            'name': input,
        }
예제 #9
0
def reverse_dns_lookup(input, timeout=3, server=''):
    """Perform a simple reverse DNS lookup, return results in a dictionary"""
    assert _REVERSE_DNS_REGEX.search(
        input), "Invalid address format: '{0}'".format(input)
    resolver = Resolver()
    resolver.timeout = float(timeout)
    resolver.lifetime = float(timeout)
    if server:
        resolver.nameservers = [server]
    try:
        tmp = input.strip().split('.')
        tmp.reverse()
        inaddr = '.'.join(tmp) + ".in-addr.arpa"
        records = resolver.query(inaddr, 'PTR')
        return {
            'name': records[0].to_text(),
            'lookup': inaddr,
            'error': '',
            'addr': input,
        }
    except DNSException as e:
        return {
            'addrs': [],
            'lookup': inaddr,
            'error': repr(e),
            'name': input,
        }
예제 #10
0
def dns_resolver():
    """
    dns解析器
    """
    resolver = Resolver()
    resolver.nameservers = config.resolver_nameservers
    resolver.timeout = config.resolver_timeout
    resolver.lifetime = config.resolver_lifetime
    return resolver
예제 #11
0
파일: resolve.py 프로젝트: zsdlove/bayonet
def dns_resolver():
    """
    dns解析器
    """
    resolver = Resolver()
    resolver.nameservers = Oneforall.resolver_nameservers
    resolver.timeout = Oneforall.resolver_timeout
    resolver.lifetime = Oneforall.resolver_lifetime
    return resolver
예제 #12
0
def dns_resolver():
    """
    dns解析器
    """
    resolver = Resolver()
    resolver.nameservers = settings.resolver_nameservers
    resolver.timeout = settings.resolver_timeout
    resolver.lifetime = settings.resolver_lifetime
    return resolver
예제 #13
0
def query_dns_server(record, type):
    resolver = Resolver(configure=False)
    resolver.nameservers = [socket.gethostbyname(auth_ns)]
    resolver.timeout = 5
    resolver.lifetime = 5
    try:
        dns_query = resolver.query(record, type)
        return dns_query
    except NXDOMAIN:
        return False
예제 #14
0
def checkWildcard(timestamp, domain):
    resolver = Resolver()
    resolver.timeout = 1
    resolver.lifetime = 1

    try:
        return (domain, gethostbyname_ex(".".join([str(timestamp),
                                                   domain]))[2])

    except Exception:
        return (domain, None)
def fqdn_ip(fqdn):
    """
    Returns the list of IPs for a fqdn
    """
    resolvers = dict()
    resolvers['local'] = dict()
    resolvers['private'] = dict()

    local_resolver = Resolver()
    local_resolver.timeout = 2
    local_resolver.lifetime = 2
    resolvers['local']['resolver'] = local_resolver

    private_resolver = Resolver()
    private_resolver.timeout = 2
    private_resolver.lifetime = 2
    private_resolver.nameservers = settings.PRIVATE_DNS_RESOLVERS
    resolvers['private']['resolver'] = private_resolver

    for resolver_name in resolvers:
        resolvers[resolver_name]['result'] = resolve_fqdn_ip(
            fqdn, resolvers[resolver_name]['resolver'], resolver_name)

    result_quorum = dict()
    result_quorum['No IP'] = 0
    result_ip = 'No IP'
    for resolver_name in resolvers:
        if resolvers[resolver_name]['result'] == 'No IP':
            return 'No IP'
        _ip = resolvers[resolver_name]['result']
        if _ip not in result_quorum:
            result_quorum[_ip] = 1
        else:
            result_quorum[_ip] += 1
        if _ip != result_ip and result_quorum[_ip] > result_quorum[result_ip]:
            result_ip = _ip

    return result_ip
예제 #16
0
def lookup(servers, domain):
    dns_resolver = Resolver()
    dns_resolver.nameservers = servers
    dns_resolver.lifetime = 3
    try:
        # python 3.9 query deprecation
        if sys.version_info.minor < 9:
            answer = dns_resolver.query(domain)
        else:
            answer = dns_resolver.resolve(domain)
        return [x.to_text() for x in answer]
    except (DNSException, ValueError) as e:
        pass
    return []
예제 #17
0
def parse_dnsname(host_input):
    output = []
    try:
        res = Resolver()
        res.timeout = 3
        res.lifetime = 3
        dns_query = res.query(host_input, "A")
        dns_query.nameservers = ['8.8.8.8', '8.8.4.4']
        for ip in dns_query:
            if REGEX['single'].match(str(ip)):
                output.append(str(ip))
    except:
        raise Exception('Could not Resolve \'{}\'\n'.format(host_input))
    return output
예제 #18
0
def parse_dnsname(host_input, ns=[]):
    output = []
    try:
        res = Resolver()
        res.timeout = 3
        res.lifetime = 3
        if ns:
            res.nameservers = ns
        for ip in res.query(host_input, "A"):
            if REGEX['single'].match(str(ip)):
                output.append(str(ip))
    except:
        raise Exception('Could not Resolve \'{}\'\n'.format(host_input))
    return output
예제 #19
0
파일: TakeOver.py 프로젝트: gfek/Lepus
def findNX(domainToTry):
    resolver = Resolver()
    resolver.timeout = 1
    resolver.lifetime = 1

    try:
        resolver.query(domainToTry)

    except NXDOMAIN:
        return True

    except Exception:
        pass

    return False
예제 #20
0
def resolve_host(host, dns_server):
    # Reuses ldap_srv value to resolve dns names (Assumes this is a DC)
    try:
        res = Resolver()
        res.timeout = 3
        res.lifetime = 3
        res.nameservers = [dns_server]
        dns_query = res.query(host, "A")
        for ip in dns_query:
            return ip
    except KeyboardInterrupt:
        exit(0)
    except:
        pass
    return ''
예제 #21
0
def perform_lookup(server, domain, timeout=3, tries=1):
    # create DNS resolver
    dns_resolver = Resolver()
    dns_resolver.nameservers = [server]
    dns_resolver.lifetime = timeout

    # try (tries) times
    for _ in range(0, tries):
        try:
            answer = dns_resolver.query(domain)
            return [r.to_text() for r in answer]
        except (DNSException, ValueError) as e:
            pass

    return None
예제 #22
0
def dns_resolver():
    """
    dns解析器
    """
    resolver = Resolver()
    resolver.nameservers = [
        '223.5.5.5',  # AliDNS
        '119.29.29.29',  # DNSPod
        '114.114.114.114',  # 114DNS
        '8.8.8.8',  # Google DNS
        '1.1.1.1'  # CloudFlare DNS
    ]
    resolver.timeout = 5.0
    resolver.lifetime = 10.0
    return resolver
예제 #23
0
def dns6_lookup(input, timeout=3, server=''):
    """Perform a simple DNS lookup, return results in a dictionary"""
    resolver = Resolver()
    resolver.timeout = float(timeout)
    resolver.lifetime = float(timeout)
    if server:
        resolver.nameservers = [server]
    try:
        records = resolver.query(input, 'AAAA')
        return {'addrs': [ii.address for ii in records],
            'error': '',
            'name': input,
            }
    except DNSException as e:
        return {'addrs': [], 
            'error': repr(e),
            'name': input,
            }
예제 #24
0
def dns6_lookup(input, timeout=3, server=''):
    """Perform a simple DNS lookup, return results in a dictionary"""
    resolver = Resolver()
    resolver.timeout = float(timeout)
    resolver.lifetime = float(timeout)
    if server:
        resolver.nameservers = [server]
    try:
        records = resolver.query(input, 'AAAA')
        return {'addrs': [ii.address for ii in records],
            'error': '',
            'name': input,
            }
    except DNSException as e:
        return {'addrs': [], 
            'error': repr(e),
            'name': input,
            }
예제 #25
0
def query(domain, query_type, timeout=5.0):
    answers = []
    res_list = []
    resl = Resolver()
    resl.timeout = timeout
    resl.lifetime = 2.0

    try:
        answers = resl.query(domain, query_type)
    except Exception as e:
        pass

    for dns_domain in answers:
        try:
            res_list.append(str(dns_domain).rstrip('.'))
        except socket.gaierror as e:  # skip non resolvable name server
            pass

    return res_list
예제 #26
0
def retrieveDNSRecords(db, domain):
	resolver = Resolver()
	resolver.timeout = 1
	resolver.lifetime = 1
	types = ["A", "MX", "NS", "AAAA", "SOA", "TXT"]
	timestamp = int(time())

	print(colored("[*]-Retrieving DNS Records...", "yellow"))

	for type in types:
		try:
			answers = resolver.query(domain, type)

			for answer in answers:
				if type == "A":
					db.add(Record(domain=domain, type=type, value=answer.address, timestamp=timestamp))

				if type == "MX":
					db.add(Record(domain=domain, type=type, value=answer.exchange.to_text()[:-1], timestamp=timestamp))

				if type == "NS":
					db.add(Record(domain=domain, type=type, value=answer.target.to_text()[:-1], timestamp=timestamp))

				if type == "AAAA":
					db.add(Record(domain=domain, type=type, value=answer.address, timestamp=timestamp))

				if type == "SOA":
					db.add(Record(domain=domain, type=type, value=answer.mname.to_text()[:-1], timestamp=timestamp))

				if type == "TXT":
					db.add(Record(domain=domain, type=type, value=str(answer), timestamp=timestamp))

				try:
					db.commit()

				except (IntegrityError, FlushError):
					db.rollback()

		except Exception as e:
			pass

	for row in db.query(Record).filter(Record.domain == domain).order_by(Record.type):
		print("  \__ {0}: {1}".format(colored(row.type, "cyan"), colored(row.value, "yellow")))
예제 #27
0
    def process(self, headers, content):
        request = Services.get("request_factory")
        hostname = urlparse(request.url).hostname
        try:
            resolver = Resolver(configure=False)
            resolver.nameservers = [settings.dns_resolver]
            resolver.timeout = 2
            resolver.lifetime = 2
            dns_query = resolver.query(hostname + ".cdn.cloudflare.net", "A")

            if len(dns_query) > 0:
                return "Cloudflare CDN"

        except NXDOMAIN:
            pass
        except NoAnswer:
            pass
        except Timeout:
            pass
예제 #28
0
    def emitter(self):

        try:
            if self.PROPERTIES['resolvers']['Value']:
                nameservers = [
                    x.strip()
                    for x in self.PROPERTIES['resolvers']['Value'].split(',')
                ]
                nameservers = self.PROPERTIES['resolvers']['Value'].split(',')
            else:
                nameservers = get_default_resolver().nameservers

            for payload in self.encoder(self.payload):
                try:
                    if self.PROPERTIES['subdomain']['Value']:
                        dnsname = '%s.%s.%s.' % (
                            self.dnsb64escape(payload),
                            self.PROPERTIES['subdomain']['Value'],
                            self.PROPERTIES['domain']['Value'])
                    else:
                        dnsname = '%s.%s.' % (self.dnsb64escape(
                            payload), self.PROPERTIES['domain']['Value'])

                        print nameservers
                    for ns in nameservers:
                        r = Resolver()
                        r.lifetime = 1
                        print ns, dnsname
                        r.nameservers = [ns]
                        try:
                            r.query(dnsname, 'A', raise_on_no_answer=False)
                        except Timeout:
                            pass  # Timed out, that's fine

                except Exception as e:
                    self.logger.error('Exception in %s: %s' %
                                      (self.__class__.__name__, e))
                    pass
        except Exception as e:
            raise

        return True
예제 #29
0
def dns6_lookup(input, timeout=3, server=""):
    """Perform a simple DNS lookup, return results in a dictionary"""
    resolver = Resolver()
    resolver.timeout = float(timeout)
    resolver.lifetime = float(timeout)
    if server:
        resolver.nameservers = [server]
    try:
        records = resolver.query(input, "AAAA")
        return {
            "addrs": [ii.address for ii in records],
            "error": "",
            "name": input,
        }
    except DNSException as e:
        return {
            "addrs": [],
            "error": repr(e),
            "name": input,
        }
예제 #30
0
    def process(self, headers, content):
        request = Services.get('request_factory')
        hostname = urlparse(request.url).hostname
        try:
            resolver = Resolver(configure=False)
            resolver.nameservers = [settings.dns_resolver]
            resolver.timeout = 2
            resolver.lifetime = 2

            dns_query = resolver.query(hostname + ".edgekey.net", 'A')

            if len(dns_query) > 0:
                return "Akamai CDN"

        except NXDOMAIN:
            pass
        except NoAnswer:
            pass
        except Timeout:
            pass
예제 #31
0
    def get_ip_from_nameserver(self, hostname, dns_ip):

        a_records = []
        resolver = Resolver()
        resolver.nameservers = [dns_ip]
        resolver.timeout = 1
        resolver.lifetime = 1
        try:
            for rdata in resolver.query(hostname, 'A'):
                a_records.append(str(rdata))
        except NoAnswer:
            return None
        except NXDOMAIN:
            return None
        except NoNameservers:
            return None
        except Timeout:
            return None

        return (a_records[0])
예제 #32
0
    def resolve(self, name, rrtype):
        domain = dns.name.from_text(name)
        dnsResolver = Resolver()
        dnsResolver.lifetime = 5
        # just an example
        result = ''
        try:
            answers = dnsResolver.query(domain, rrtype)
            for answer in answers:
                if rrtype == 'MX':
                    result = answer.exchange
                    logging.debug('%s is %s' % (rrtype, result))
                else:
                    raise Exception("unsupported type!")
        except DNSException as ex:
            logging.error("resolve() DNSException: %s" % ex.__class__)
            raise Exception(ex.__class__)

        except Exception as ex:
            logging.error("resolve() exception: %s" % ex)
            raise ex
        return result
예제 #33
0
    def resolve(self, name, rrtype):
        domain = dns.name.from_text(name)
        dnsResolver = Resolver()
        dnsResolver.lifetime = 5
        # just an example
        result = ''
        try:
            answers = dnsResolver.query(domain, rrtype)
            for answer in answers:
                if rrtype == 'MX':
                    result = answer.exchange
                    logging.debug('%s is %s' % (rrtype, result))
                else:
                    raise Exception("unsupported type!")
        except DNSException as ex:
            logging.error("resolve() DNSException: %s" % ex.__class__)
            raise Exception(ex.__class__)

        except Exception as ex:
            logging.error("resolve() exception: %s" % ex)
            raise ex
        return result
예제 #34
0
파일: dns.py 프로젝트: ubnetdef/scoreengine
def check_dns(check, data):
	check.addOutput("ScoreEngine: {} Check\n".format(check.getServiceName()))
	check.addOutput("EXPECTED: Sucessful and correct query against the DNS server")
	check.addOutput("OUTPUT:\n")

	# Setup the resolver
	resolv = Resolver()
	resolv.nameservers = [data["HOST"]]
	resolv.timeout = dns_config["timeout"]
	resolv.lifetime = dns_config["lifetime"]

	check.addOutput("Starting check...")

	try:
		# Query resolver
		check.addOutput("Querying {HOST} for '{LOOKUP}'...".format(**data))
		lookup = resolv.query(data["LOOKUP"], data["TYPE"])

		found = False
		for ans in lookup:
			if str(ans) == data["EXPECTED"]:
				found = True
			else:
				check.addOutput("NOTICE: DNS Server returned {}".format(ans))

		if not found:
			check.addOutput("ERROR: DNS Server did not respond with the correct IP")
			return

		# We're good!
		check.setPassed()
		check.addOutput("Check successful!")
	except Exception as e:
		check.addOutput("ERROR: {}: {}".format(type(e).__name__, e))

		return
예제 #35
0
def main():

    # parse and check command line args
    (options, args) = parse_args()
    if (len(options.ensure_value('resolvers', [])) != 2
        or len(args) != 1):
        usage()
        sys.exit()

    if options.run_tests:
        test()
        sys.exit()

    #copy arg values from parser output
    resolver_ips = options.resolvers
    verbose = options.verbose
    question_file = args[0]
    ttl_tolerance = int(options.ttl_tolerance)
    side_by_side = options.side_by_side

    #create dns resolvers (no dnssec for now)
    #source_ips is a list parallel to resolvers that contains the IPv4 address
    #to bind the query source address to -so you can control which interface the
    #query comes from - useful for testing on a machine with multiple nics.
    resolvers = []
    source_ips = []
    for resolver_ip in resolver_ips:

        resolver = Resolver()
        if resolver_ip.find('/') > 0:
            parts = resolver_ip.split('/')
            resolver.nameservers = [parts[0]]
            source_ips.append(parts[1])
        else:
            resolver.nameservers = [resolver_ip]
            source_ips.append(None)
        resolver.retry_servfail = True
        #resolver.use_edns(0, DO, 1200)
        resolver.lifetime = 5

        resolvers.append(resolver)

    #only compare 2 resolvers for now
    if len(resolvers) > 2:
        print("only 2 resolvers allowed for now..., picking first 2")
        resolvers = resolvers[:2]

    #loop over the question input and compare the results from the resolvers
    lineno = 0
    for line in file(question_file):

        #allow blank lines or lines that start with #
        if len(line.strip()) == 0 or line.lstrip().startswith("#"):
            continue

        #assume anything else is a question: <name> <rdtype> [<rdclass>]
        parts = line.strip().split(' ')
        name = parts[0].strip()
        rdtype = parts[1].strip()
        rdclass = parts[2].strip() if len(parts) > 2 else 'IN'
        lineno += 1

        results = []
        rtt_time = []
        for resolver, source_ip in zip(resolvers, source_ips):

            try:
                start_time = time.time()
                result = resolver.query(name, rdtype, rdclass, source=source_ip, raise_on_no_answer=False)
                end_time = time.time()

                results.append(result)
                rtt_time.append(end_time - start_time)

            except NXDOMAIN, nxd:
                results.append(nxd)
                rtt_time.append(-1)
            except YXDOMAIN, yxd:
                results.append(yxd)
                rtt_time.append(-1)
            except NoAnswer, noa:
                results.append(noa)
                rtt_time.append(-1)
예제 #36
0
def dns_query(input="", query_type="", server="", timeout=2.0):
    """A unified IPv4 & IPv6 DNS lookup interface; this is essentially just a wrapper around dnspython's API.  When you query a PTR record, you can use an IPv4 or IPv6 address (which will automatically be converted into an in-addr.arpa name.  This wrapper only supports a subset of DNS records: 'A', 'AAAA', 'CNAME', 'MX', 'NS', 'PTR', and 'TXT'

    Kwargs:
        - input (str): A string containing the DNS record to lookup
        - query_type (str): A string containing the DNS record type (SOA not supported)
        - server (str): A string containing the fqdn or IP address of the dns server
        - timeout (float): DNS lookup timeout duration (default: 2.0 seconds)

    Returns:
        A set() of :class:`~ccp_util.DNSResponse` instances

>>> from ciscoconfparse.ccp_util import dns_query
>>> dns_query('www.pennington.net', "A", "4.2.2.2")
set([<DNSResponse "A" result_str="65.19.187.2">])
>>> answer = dns_query('www.pennington.net', 'A', '4.2.2.2')
>>> str(answer.pop())
'65.19.187.2'
>>>
    """

    valid_records = set(['A', 'AAAA', 'AXFR', 'CNAME', 'MX', 'NS', 'PTR', 
        'TXT'])
    query_type = query_type.upper()
    assert query_type in valid_records
    assert server!=""
    assert float(timeout)>0
    assert input != ""
    intput = input.strip()
    retval = set([])
    resolver = Resolver()
    resolver.server = [socket.gethostbyname(server)]
    resolver.timeout = float(timeout)
    resolver.lifetime = float(timeout)
    start = time.time()
    if (query_type=="A") or (query_type=="AAAA"):
        try:
            answer = resolver.query(input, query_type)
            duration = time.time() - start
            for result in answer:
                response = DNSResponse(query_type=query_type, 
                    duration=duration,
                    input=input, result_str = str(result.address))
                retval.add(response)
        except DNSException as e:
                duration = time.time() - start
                response = DNSResponse(input=input, 
                    duration=duration, query_type=query_type)
                response.has_error = True
                response.error_str = e
                retval.add(response)
    elif query_type=="AXFR":
        """This is a hack: return text of zone transfer, instead of axfr objs"""
        _zone = zone.from_xfr(query.xfr(server, input, lifetime=timeout))
        return [_zone[node].to_text(node) for node in _zone.nodes.keys()]
    elif query_type=="CNAME":
        try:
            answer = resolver.query(input, query_type)
            duration = time.time() - start
            for result in answer:
                response = DNSResponse(query_type=query_type, 
                    duration=duration, 
                    input=input, result_str = str(result.target))
                retval.add(response)
        except DNSException as e:
                duration = time.time() - start
                response = DNSResponse(input=input, duration=duration,
                    query_type=query_type)
                response.has_error = True
                response.error_str = e
                retval.add(response)
    elif query_type=="MX":
        try:
            answer = resolver.query(input, query_type)
            duration = time.time() - start
            for result in answer:
                response = DNSResponse(query_type=query_type, 
                    input=input, result_str = str(result.target))
                response.preference = int(result.preference)
                retval.add(response)
        except DNSException as e:
                duration = time.time() - start
                response = DNSResponse(input=input, duration=duration,
                    query_type=query_type)
                response.has_error = True
                response.error_str = e
                retval.add(response)
    elif query_type=="NS":
        try:
            answer = resolver.query(input, query_type)
            duration = time.time() - start
            for result in answer:
                response = DNSResponse(query_type=query_type, 
                    duration=duration,
                    input=input, result_str = str(result.target))
                retval.add(response)
        except DNSException as e:
                duration = time.time() - start
                response = DNSResponse(input=input, 
                    duration=duration, query_type=query_type)
                response.has_error = True
                response.error_str = e
                retval.add(response)
    elif query_type=="PTR":
        if is_valid_ipv4_addr(input) or is_valid_ipv6_addr(input):
            inaddr = reversename.from_address(input)
        elif 'in-addr.arpa' in input.lower():
            inaddr = input
        else:
            raise ValueError('Cannot query PTR record for "{0}"'.format(input))

        try:
            answer = resolver.query(inaddr, query_type)
            duration = time.time() - start
            for result in answer:
                response = DNSResponse(query_type=query_type, 
                    duration=duration,
                    input=inaddr, result_str = str(result.target))
                retval.add(response)
        except DNSException as e:
                duration = time.time() - start
                response = DNSResponse(input=input, 
                    duration=duration,
                    query_type=query_type)
                response.has_error = True
                response.error_str = e
                retval.add(response)
    elif query_type=="TXT":
        try:
            answer = resolver.query(input, query_type)
            duration = time.time() - start
            for result in answer:
                response = DNSResponse(query_type=query_type, 
                    duration=duration,
                    input=inaddr, result_str = str(result.strings))
                retval.add(response)
        except DNSException as e:
                duration = time.time() - start
                response = DNSResponse(input=input, 
                    duration=duration, query_type=query_type)
                response.has_error = True
                response.error_str = e
                retval.add(response)
    return retval