Example #1
0
 def fetch_dns(self):
     try:
         name_server = self.settings.get("dns", "server")
         keyring = dns.tsigkeyring.from_text(
                 {self.settings.get("dns", "tsig_name"):
                  self.settings.get("dns", "tsig_key")}
         )
         for domain in self.settings.get("dns", "domains").split(","):
             try:
                 responses = query.xfr(
                         name_server,
                         dns_name.from_text(domain),
                         keyring=keyring,
                         keyname=self.settings.get("dns", "tsig_name"),
                         keyalgorithm=dns.tsig.HMAC_SHA512
                 )
                 with open(pjoin(self.configs, "dns." + domain),
                           "w") as config:
                     for response in responses:
                         for line in response.answer:
                             config.write(line.to_text() + u"\n")
             except:
                 pass
     except:
         logging.error("can't fetch from DNS: %s" %
                       self.settings.get('dns', 'server'))
    def zone_transfer(logger, url):
        '''
            This function is responsible to try to get the `zone transfer` file.
            If he success, he shows the `zone transfer` file and he will finish.

            How this function works?
            he get all the DNS Records and try to get the `zone transfer` file by all the records.
            If he failed, he will continue to try to get the `zone transfer file` by the next DNS record.
            If all the records will fail, we cant to get a `zone transfer` file.
            The function will returns false value.
        '''
        try:
            logger.info("[DNS] Trying zone transfer first..")
            answers = resolver.query(url, 'NS')
            for ns in (ns.to_text().rstrip('.') for ns in answers):
                try:
                    z = zone.from_xfr(
                        query.xfr(ns, url)
                    )
                    zone_record = "\n".join(z[z_node].to_text(z_node) for z_node in z.nodes.keys())
                    logger.info("[DNS] Zone file:!\n%s" % zone_record)
                    return True
                except socket.error:
                    pass
        except (FormError, dns.resolver.NoAnswer, dns.exception.Timeout, EOFError):
            pass
        except Exception as e:
            logger.error('[DNS][Error] %s' % e.message)
        return False
Example #3
0
    def zone_transfer(logger, url):
        '''
            This function is responsible to try to get the `zone transfer` file.
            If he success, he shows the `zone transfer` file and he will finish.

            How this function works?
            he get all the DNS Records and try to get the `zone transfer` file by all the records.
            If he failed, he will continue to try to get the `zone transfer file` by the next DNS record.
            If all the records will fail, we cant to get a `zone transfer` file.
            The function will returns false value.
        '''
        try:
            logger.info("[DNS] Trying zone transfer first..")
            answers = resolver.query(url, 'NS')
            for ns in (ns.to_text().rstrip('.') for ns in answers):
                try:
                    z = zone.from_xfr(query.xfr(ns, url))
                    zone_record = "\n".join(z[z_node].to_text(z_node)
                                            for z_node in z.nodes.keys())
                    logger.info("[DNS] Zone file:!\n%s" % zone_record)
                    return True
                except socket.error:
                    pass
        except (FormError, dns.resolver.NoAnswer, dns.exception.Timeout,
                EOFError):
            pass
        except Exception as e:
            logger.error('[DNS][Error] %s' % e.message)
        return False
Example #4
0
    def pull_zone(self, nameserver):
        """Sends the domain transfer request"""
        try:
            q = query.xfr(nameserver,
                          self.domain,
                          relativize=False,
                          timeout=2,
                          lifetime=5)
        except dns.exception.Timeout:
            raise EOFError
        zone = {}

        for m in q:
            for rrset in m.answer:
                for rd in rrset:
                    # result_string = str(rrset.name).ljust(30) + str(dns.rdatatype.to_text(rrset.rdtype)).ljust(10) + rd.to_text(origin=None, relativize=True)
                    # zone += result_string + '\
                    parse_type = dns.rdatatype.to_text(rrset.rdtype)
                    if parse_type == 'A':
                        sub_domain = str(rrset.name)
                        if re.match(r'^.*\.$', sub_domain):
                            sub_domain = sub_domain[:-1]
                        zone[sub_domain] = rd.to_text(origin=None,
                                                      relativize=True)
        if not zone:
            raise EOFError
        return zone
    def discover(self):
        new_serial = self.remote_soa_serial()

        if self.serial and self.serial == new_serial:
            log.debug("No change of SOA serial")
            return

        for item in six.itervalues(self._patterns):
            item.accumulator = set()

        for message in xfr(self.ip, self.domain, port=self.port, use_udp=False, rdtype=self.rdtype):
            for answer in message.answer:
                if answer.rdtype in [A, AAAA, CNAME] and answer.name:
                    for pattern, item in six.iteritems(self._patterns):
                        if pattern.match(answer.name.labels[0]):
                            item.accumulator.add(str(answer.name))

        for item in six.itervalues(self._patterns):
            log.debug("{}: {}".format(new_serial, item.accumulator))
            item.accumulator.difference_update(item.items)
            gone = item.items.difference(item.accumulator)
            for callback in item.callbacks:
                callback(item.accumulator, gone)

            item.items.update(item.accumulator)

        self.serial = new_serial
    def discover(self):
        new_serial = self.remote_soa_serial()

        if self.serial and self.serial == new_serial:
            log.debug("No change of SOA serial")
            return

        for item in six.itervalues(self._patterns):
            item.accumulator = set()

        for message in xfr(self.ip,
                           self.domain,
                           port=self.port,
                           use_udp=False,
                           rdtype=self.rdtype,
                           keyname=self.keyname,
                           keyring=self.keyring):
            for answer in message.answer:
                if answer.rdtype in [A, AAAA, CNAME] and answer.name:
                    for pattern, item in six.iteritems(self._patterns):
                        if pattern.match(answer.name.labels[0]):
                            item.accumulator.add(str(answer.name))

        for item in six.itervalues(self._patterns):
            log.debug("{}: {}".format(new_serial, item.accumulator))
            item.accumulator.difference_update(item.items)
            gone = item.items.difference(item.accumulator)
            for callback in item.callbacks:
                callback(item.accumulator, gone)

            item.items.update(item.accumulator)

        self.serial = new_serial
Example #7
0
 def pull_zone(self, nameserver):
     """Sends the domain transfer request"""
     q = query.xfr(nameserver, self.domain, relativize=False, timeout=2)
     zone = ""   ## janky, but this library returns
     for m in q: ## an empty generator on timeout
         zone += str(m)
     if not zone:
         raise EOFError
     return zone
Example #8
0
 def pull_zone(self, nameserver):
     """Sends the domain transfer request"""
     q = query.xfr(nameserver, self.domain, relativize=False, timeout=2)
     zone = ""
     for m in q:
         zone += str(m)
     if not zone:
         raise EOFError
     return zone
 def pull_zone(self, nameserver):
     """Sends the domain transfer request"""
     q = query.xfr(nameserver, self.domain, relativize=False, timeout=2)
     zone = ""  ## janky, but this library returns
     for m in q:  ## an empty generator on timeout
         zone += str(m)
     if not zone:
         raise EOFError
     return zone
 def pull_zone(self, nameserver):
     """Sends the domain transfer request"""
     q = query.xfr(nameserver, self.domain, relativize=False, timeout=2)
     zone = ""   
     for m in q: 
         zone += str(m)
     if not zone:
         raise EOFError
     return zone
Example #11
0
 def remote_soa_serial(self):
     for message in xfr(self.ip,
                        self.domain,
                        port=self.port,
                        use_udp=False,
                        rdtype=SOA,
                        keyname=self.keyname,
                        keyring=self.keyring):
         for answer in message.answer:
             if answer.rdtype == SOA:
                 return answer[0].serial
     return None
Example #12
0
    def __do_dns_transfer(self, ip: str) -> List[str]:
        """Do the DNS Zone Transfer, returning the subdomains

        @type ip: str
        @param ip: The IP from the name server
        @returns List[str]: The list with the subdomains
        """
        try:
            zones = zone.from_xfr(query.xfr(ip.rstrip('.'), self.host))
        except query.TransferError:
            return []
        else:
            return [str(subdomain) for subdomain in zones]
Example #13
0
def AXFR(domain, nameserver):

    try:
        axfr = dz.from_xfr(dq.xfr(nameserver, domain))

        if axfr:
            print('[*] Successful Zone Transfer from {}'.format(nameserver))

            for record in axfr:
                Subdomains.append('{}.{}'.format(record.to_text(), domain))

    except Exception as error:
        print(error)
        pass
Example #14
0
    def get_axfr_records(self, server, domains):
        """Return a `list` of `dict`s containing the zones and their records, obtained from the DNS server

        Returns:
            :obj:`list` of `dict`
        """
        zones = []
        for zoneName in domains:
            try:
                zone = {
                    'zone_id': get_resource_id('axfrz', zoneName),
                    'name': zoneName,
                    'source': 'AXFR',
                    'comment': None,
                    'tags': {},
                    'records': []
                }

                z = dns_zone.from_xfr(query.xfr(server, zoneName))
                rdata_fields = ('name', 'ttl', 'rdata')
                for rr in [
                        dict(zip(rdata_fields, x)) for x in z.iterate_rdatas()
                ]:
                    record_name = rr['name'].derelativize(z.origin).to_text()
                    zone['records'].append({
                        'id':
                        get_resource_id(
                            'axfrr', record_name,
                            ['{}={}'.format(k, str(v))
                             for k, v in rr.items()]),
                        'zone_id':
                        zone['zone_id'],
                        'name':
                        record_name,
                        'value':
                        sorted([rr['rdata'].to_text()]),
                        'type':
                        type_to_text(rr['rdata'].rdtype)
                    })

                if len(zone['records']) > 0:
                    zones.append(zone)

            except Exception as ex:
                self.log.exception(
                    'Failed fetching DNS zone information for {}: {}'.format(
                        zoneName, ex))
                raise

        return zones
Example #15
0
def perform_zone_transfer(domain, server):

    serv_addr = resolver.resolve(server, "A")[0].address

    try:
        records = zone.from_xfr(query.xfr(serv_addr, domain))

        deliverable = []

        for record in sorted(records.nodes.keys()):
            deliverable.append(records[record].to_text(record))

    except xfr.TransferError:
        return False

    return deliverable
Example #16
0
def zoneTransfer(db, domain):
	print(colored("\n[*]-Attempting to zone transfer from the identified nameservers...", "yellow"))

	for row in db.query(Record).filter(Record.domain == domain, Record.type == "NS"):
		try:
			zone = from_xfr(xfr(row.value, domain))
			subdomains = set([str(key) for key in zone.nodes.keys()])

			print("  \__ {0}: {1}".format(colored("Subdomains retrieved", "cyan"), colored(len(subdomains), "yellow")))
			return subdomains

		except Exception:
			continue

	print("  \__", colored("Failed to zone transfer.", "red"))
	return None
def AXFR(domain, nameserver):
    # Try zone transfer for given domain and namerserver
    try:
        # Perform the zone transfer
        axfr = dz.from_xfr(dq.xfr(nameserver, domain))

        # If zone transfer was successful
        if axfr:
            print('[*] Successful Zone Transfer from {}'.format(nameserver))

            # Add found subdomains to global 'Subdomain' list
            for record in axfr:
                Subdomains.append('{}.{}'.format(record.to_text(), domain))

    # If zone transfer fails
    except Exception as error:
        print(error)
        pass
Example #18
0
    def dump(self):
        try:
            z = zone.from_xfr(query.xfr(self.server, self.domain,
                        timeout=10))
        except:
            print "Exception in bind9.BIND9.dump() on zone xfr"

        for name, node in z.nodes.items():
            if str(name) == '@': continue
            rdatasets = node.rdatasets
            for rdataset in rdatasets:
                if rdataset.rdclass == IN and rdataset.rdtype in [A, CNAME]:
                    record = str(rdataset).split(' ')
                    self.records[str(name)] = {
                        'ttl': record[0],
                        'type': record[2],
                        'resolveto': record[3],
                        }
        return self.records
Example #19
0
    def remote_soa_serial(self):
        try:
            # returns an iterator, that's evaluated lazily
            messages = xfr(self.ip,
                           self.domain,
                           port=self.port,
                           use_udp=False,
                           rdtype=SOA,
                           keyname=self.keyname,
                           keyring=self.keyring,
                           keyalgorithm=KEYALGORITHM)
            for message in messages:
                for answer in message.answer:
                    if answer.rdtype == SOA:
                        return answer[0].serial
        except (OSError, EOFError):
            LOG.exception('Handled an exception on retrieving the new SOA '
                          'serial gracefully.')

        return None
Example #20
0
def AXFR(domain, nameserver):

    # Try zone transfer for given domain and namerserver
    try:
        # Perform the zone transfer
        # print("NS: " + nameserver + " - Domain: " + domain)
        axfr = dz.from_xfr(dq.xfr(nameserver, domain), check_origin=False)
        # print(axfr)

        # If zone transfer was successful
        if axfr:
            print("\n[*] Successful Zone Transfer from {}".format(nameserver))

            # Add found subdomains to global 'Subdomain' list
            for record in axfr:
                Subdomains.append("{}.{}".format(record.to_text(), domain))

    # If zone transfer fails
    except Exception as error:

        print(error)
        pass
Example #21
0
def get_target_subdomains_from_auth_ns(target, auth_ns):
    """ Checks domains nameserver for zone transfers, if allowed returns a list of enumerated subdomain DNS records"""
    if valid_ip(target):  # handle IPs
        try:
            gethostbyaddr(str(target))
        except herror:
            print(RED + "Could not get hostname from " + str(target) +
                  ", check target is live/up." + END)
            exit(-1)
    try:
        z = from_xfr(xfr(str(auth_ns),
                         target))  # zone transfer dig request using auth ns
        subdomains = []
        names = z.nodes.keys()  # node key values
        for n in names:
            at = match("@", str(n))  # removes dns self (@) symbol
            if not at:
                subdomain = str(n) + "." + target
                subdomains.append(subdomain)
                # print(subdomain)
        print(RED + target, "is VULNERABLE to DNS Zone Transfers!!!" + END)
        return subdomains
    except TransferError:  # most domains
        print(GREEN + target, "is SECURE against DNS Zone Transfers :-)" + END)
        exit(1)
    except FormError:  # google.co.uk
        print(GREEN + target, "is SECURE against DNS Zone Transfers :-)" + END)
        exit(1)
    except TimeoutError:  # rhul.ac.uk
        print(GREEN + target,
              "is VERY SECURE against DNS Zone Transfers :-)" + END)
        exit(1)
    except OSError:  # the next router
        print(RED + "[No route to host] Lookup Failure!" + END)
        print(
            "Domain name reverse fqdn lookup error - Check your on the domains internal network, or setup dnscrypt "
            "for the domain as all european ISPs high-jack all dns traffic to censor the internet!"
        )
        exit(1)
Example #22
0
    def discover(self):
        new_serial = self.remote_soa_serial()

        if not new_serial:
            LOG.warning("Could not fetch SOA serial")
            return

        if self.serial and self.serial == new_serial:
            LOG.debug("No change of SOA serial")
            return

        for item in self._patterns.values():
            item.accumulator = set()

        for message in xfr(self.ip,
                           self.domain,
                           port=self.port,
                           use_udp=False,
                           rdtype=self.rdtype,
                           keyname=self.keyname,
                           keyring=self.keyring,
                           keyalgorithm=KEYALGORITHM):
            for answer in message.answer:
                if answer.rdtype in [A, AAAA, CNAME] and answer.name:
                    for pattern, item in self._patterns.items():
                        if pattern.match(answer.name.labels[0]):
                            item.accumulator.add(str(answer.name))

        for item in self._patterns.values():
            LOG.debug(f"{new_serial}: {item.accumulator}")
            item.accumulator.difference_update(item.items)
            gone = item.items.difference(item.accumulator)
            for callback in item.callbacks:
                callback(item.accumulator, gone)

            item.items.update(item.accumulator)

        self.serial = new_serial
Example #23
0
def zoneTransfer(nameservers, domain):
    print(
        colored(
            "\n[*]-Attempting to zone transfer from the identified nameservers...",
            "yellow"))

    for nameserver in nameservers:
        try:
            zone = from_xfr(xfr(nameserver, domain))
            hosts = [
                "{0}.{1}".format(key, domain)
                for key in sorted(list(set(zone.nodes.keys())))
            ]

            print("  \__", colored("Unique subdomains retrieved:", "cyan"),
                  colored(len(hosts), "yellow"))

            try:
                with open(join("results", domain, "zone_transfer.txt"),
                          "w") as zone_file:
                    for host in hosts:
                        zone_file.write("{0}\n".format(host))

            except OSError:
                pass

            except IOError:
                pass

            return hosts

        except Exception:
            continue

    print("  \__", colored("Failed to zone transfer.", "red"))
    return []
Example #24
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
 def remote_soa_serial(self):
     for message in xfr(self.ip, self.domain, port=self.port, use_udp=False, rdtype=SOA):
         for answer in message.answer:
             if answer.rdtype==SOA:
                 return answer[0].serial
     return None
Example #26
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
Example #27
0
def main():
    parser = argparse.ArgumentParser(description='Process some integers.')
    parser.add_argument('-d', action="store", type=str, dest="view")
    parser.add_argument('-s', action="store", type=str, dest="server")
    parser.add_argument('-l', action="store", type=int, dest="zone_limit")
    parser.add_argument('-o', action="store", type=str, dest="origin")
    parser.add_argument('-p', action="store", type=str, dest="zone_path")
    parser.add_argument('-w', action="store", type=str, dest="override_path")
    parser.add_argument('-x', action="store_true", dest="delete_unknown_zone")
    parser.add_argument('-e', action="store", dest="named_restart_command")
    args = parser.parse_args()

    config_obj = Config()
    o_config = config_obj.get_config()
    stop_update_file_path = o_config.get('Global', 'StopUpdate')
    statefile_path = o_config.get('Global', 'StateFile')

    try:
        is_config_valid, config_message = config_obj.config_valid(o_config)
    except AttributeError:
        is_config_valid = False
        config_message = "No Configuration File Found"

    if os.path.exists(stop_update_file_path):
        print "Stop Update file Exists"
        sys.exit(2)

    if is_config_valid is False:
        print config_message
        sys.exit(2)

    if not args.view:
        msg = "DNS View command line argument required"
        Common.write_stop_update(stop_update_file_path, msg)
        print msg
        sys.exit(2)

    if not args.server:
        msg = "server command line argument required"
        Common.write_stop_update(stop_update_file_path, msg)
        print msg
        sys.exit(2)

    if not args.zone_path:
        msg = "zone_path command line argument required"
        Common.write_stop_update(stop_update_file_path, msg)
        print msg
        sys.exit(2)

    named_restart_command = "service named restart"
    if args.named_restart_command:
        named_restart_command = args.named_restart_command

    override_path = None
    if args.override_path:
        override_path = args.override_path

    named_reload = False
    named_failures = None
    reload_zones = []

    api = API(o_config, args.view, origin=args.origin)

    all_records = []
    all_zones = api.build_all_zones()
    # Track all of the zone names to compare via os.listdir
    all_zone_names = []

    if args.zone_limit:
        all_zones = all_zones[:args.zone_limit]
    for zone in all_zones:
        is_reverse = Common.is_reverse_zone_name(zone)
        if is_reverse:
            zone = Common.reverse_name(zone)

        d_cmd = CMD(zone, args.server)
        output, errors = d_cmd.run()
        build = Build(output)
        all_records += build.run()

        local_zone = ZoneObject(zone, path=args.zone_path)
        local_serial = local_zone.get_serial()
        all_zone_names.append(local_zone.zone_name)

        try:
            axfr_zone = dnszone.from_xfr(query.xfr(args.server, zone))
        except dns.exception.FormError:
            axfr_zone = None
        except dns.name.EmptyLabel:
            axfr_zone = None
        except Exception, e:
            axfr_zone = None
        if axfr_zone is None or local_zone is None:
            continue

        if axfr_zone is not None:
            axfr_zone_object = ZoneObject(zone, zone_obj=axfr_zone)
            axfr_serial = axfr_zone_object.get_serial()

        if axfr_serial != local_serial:
            named_reload = True
            write_path = os.path.join(args.zone_path, zone)
            try:
                axfr_zone.to_file(write_path)
            except Exception, e:
                print "Exception: {0}".format(exception)
            reload_zones.append({'zone': zone, 'path': write_path})
Example #28
0
    def update_records(self):
        ''' Run route53 updates based on AXFR request '''
        # performing axfr
        try:
            print("Making AXFR request to " + self.options.dns_server + "...")
        except TypeError:
            raise SystemExit("No DNS server set. try again with -s to set the "
                             "server to make the AXFR request against.")
        try:
            z = dnszone.from_xfr(query.xfr(
                self.options.dns_server, self.options.domain))
        except AttributeError:
            raise SystemExit("No domin set. try again with -d to set the "
                             "domain to reuest AXFR request for.")
        if self.options.hostedzone is not None:
            print("AXFR Request recieved a reply from the server."
                  "Preping to send to R53 Hoested Zone: " +
                  str(self.options.hostedzone))
        else:
            raise SystemExit("No Hosted Zone set. try again with -z to set "
                             "the zone to submit the records to.")
        dns_changes = []
        adict = {}
        print("Processing " + str(
            self.options.recordtype) + " records for " + str(
                self.options.domain) + "...")
        if len(z.nodes) == 0:
            raise SystemExit("No records found to "
                             "process... is AXFR enabled the DNS server you "
                             "are pulling from?")
        print("Total records downloaded: " + str(len(z.nodes)))
        if self.options.recordtype == "A":
            rdtypevar = A
            rdclassvar = IN
        elif self.options.recordtype == "AAAA":
            rdtypevar = AAAA
            rdclassvar = IN
        elif self.options.recordtype == "CNAME":
            rdtypevar = CNAME
            rdclassvar = IN
        elif self.options.recordtype == "MX":
            rdtypevar = MX
            rdclassvar = IN
        elif self.options.recordtype == "NS":
            rdtypevar = NS
            rdclassvar = IN
        elif self.options.recordtype == "PTR":
            rdtypevar = PTR
            rdclassvar = IN
        elif self.options.recordtype == "SPF":
            rdtypevar = SPF
            rdclassvar = IN
        elif self.options.recordtype == "TXT":
            rdtypevar = TXT
            rdclassvar = IN
        elif self.options.recordtype == "SRV":
            rdtypevar = SRV
            rdclassvar = IN
        else:
            raise SystemExit("Unknown or unsupported record type "
                             "in Route 53: " + str(self.options.recordtype))
        for name, node in z.nodes.items():
            rdataset = None
            rdataset = node.get_rdataset(
                rdclass=rdclassvar, rdtype=rdtypevar)
            if not rdataset:
                continue
            for rds in rdataset:
                if str(name) == "@":
                    continue
                else:
                    recordname = str(name) + "." + self.options.domain + "."
                    if recordname in adict:
                        ipaddr = str(rds)
                        adict[recordname]['records'].append(ipaddr)
                    else:
                        ipaddr = str(rds)
                        adict[recordname] = {'records': [ipaddr]}
                        adict[recordname].update({'ttl': str(rdataset.ttl)})

        for key, thedict in adict.iteritems():
            ResourceRecordList = []
            for record in thedict['records']:
                ResourceRecordList.append({'Value': record})
            dns_changes.append({'Action': 'UPSERT',
                                'ResourceRecordSet': {
                                    'Name': key,
                                    'Type': self.options.recordtype,
                                    'TTL': int(thedict['ttl']),
                                    'ResourceRecords': ResourceRecordList
                                    }
                                })
        if len(dns_changes) == 0:
            raise SystemExit("No " + self.options.recordtype + " records "
                             "processed... Are there records of this type on "
                             "the DNS server you are pulling from?")
        print("Total records processed: " + str(len(dns_changes)))
        # connecting to route53 via boto
        print("Connecting to Route53 via boto3...")
        client = boto3.client('route53')
        if len(dns_changes) > 98:
            print("Breaking up records into batches of 100 "
                  "to send to Route53...")
            chunks = [dns_changes[x:x+98] for x in xrange(0, len(
                dns_changes), 98)]
            chunkcount = 0
            for chunk in chunks:
                chunkcount = chunkcount + 1
                client.change_resource_record_sets(
                    HostedZoneId=str(self.options.hostedzone),
                    ChangeBatch={'Changes': chunk})
                print("Batch " + str(chunkcount) + " submitted to Route 53")
        else:
            client.change_resource_record_sets(
                HostedZoneId=str(self.options.hostedzone),
                ChangeBatch={'Changes': dns_changes})
            print("Batch 1 submitted to Route 53")