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
Beispiel #2
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
Beispiel #3
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
Beispiel #4
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 []
Beispiel #5
0
def is_xfr_enabled(domain: str, nameserver: str) -> bool:
    """
    Check if zone transfer is enabled.

    :param domain: Name of the zone to transfer.
    :param nameserver: IPv4 or 6 to test.
    """
    axfr_query = dns.query.xfr(nameserver,
                               domain,
                               timeout=5,
                               relativize=False,
                               lifetime=10)

    result = True
    try:
        zone = from_xfr(axfr_query, relativize=False)
        if not str(zone.origin).rstrip('.'):
            show_close('Zone transfer not enabled on server',
                       details=dict(domain=domain, nameserver=nameserver))
            result = False
        result = True
        show_open('Zone transfer enabled on server',
                  details=dict(domain=domain, nameserver=nameserver))
    except (NoSOA, NoNS, BadZone, dns.query.BadResponse):
        show_close('Zone transfer not enabled on server',
                   details=dict(domain=domain, nameserver=nameserver))
        result = False
    except (socket.error, dns.exception.Timeout,
            dns.exception.FormError) as exc:
        show_unknown('Could not connect',
                     details=dict(domain=domain,
                                  nameserver=nameserver,
                                  error=str(exc).replace(':', ',')))
        result = False

    return result
Beispiel #6
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})
Beispiel #7
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
Beispiel #8
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
Beispiel #9
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")