Почему передача зоны DNS Python время от времени прекращается - PullRequest
1 голос
/ 21 марта 2020

Итак, я все еще на уровне нубов, когда дело доходит до python. Я знаю ... я знаю ... возможно, есть более эффективный способ сделать то, что я пытаюсь, но все еще учусь и, надеюсь, я поправлюсь с практикой.

Для учебного проекта я Я пишу скрипт для выполнения различных операций DNS с доменом. Я нашел DNS Python, и мне показалось, что это именно то, что мне нужно было использовать, и я подумал, что с ним покончено, но когда я попробовал его на другом домене, при передаче зоны происходит сбой.

I ' у нас прямо сейчас есть два домена для тестирования. Домен мегакорпона iw работал, как я и ожидал, однако теперь он не работает (без изменения кода), чтобы заставить его работать, мне пришлось отфильтровать первую запись '@', которая была возвращена, в противном случае она также не удалась.

Тем не менее, домен zonetransfer.me иногда завершает сценарий с ошибкой, но также периодически вызывает ошибки, но по какой-то причине он никогда не отображает записи хоста, и я не смог выяснить, как это исправить тем не менее, я уже некоторое время стучу по нему головой.

Запуск мегакопрона работал каждый раз раньше, теперь он вообще не работает. Пока я могу думать только о том, что это может быть проблема синхронизации.

Запуск с мегакопроном

Attempting zone transfers for megacorpone.com
Traceback (most recent call last):
  File "/home/kali/Exercises/Module_7/dns-axfer.py", line 56, in zoneXFR
    zone = dns.zone.from_xfr(dns.query.xfr(str(server).rstrip('.'), domain))
  File "/usr/lib/python3/dist-packages/dns/zone.py", line 1106, in from_xfr
    for r in xfr:
  File "/usr/lib/python3/dist-packages/dns/query.py", line 627, in xfr
    raise TransferError(rcode)
dns.query.TransferError: Zone transfer error: REFUSED

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/kali/Exercises/Module_7/dns-axfer.py", line 73, in <module>
    zoneXFR()
  File "/home/kali/Exercises/Module_7/dns-axfer.py", line 66, in zoneXFR
    print ("\nResults for",server, "\nZone origin:", str(zone.origin).rstrip('.'))
UnboundLocalError: local variable 'zone' referenced before assignment

Запуск 1 с zonetransfer.me

Attempting zone transfers for zonetransfer.me

Results for nsztm1.digi.ninja. 
Zone origin: zonetransfer.me
---------------------------------------------------------------------------

Results for nsztm1.digi.ninja. 
Zone origin: zonetransfer.me
---------------------------------------------------------------------------
[*]  Error: <class 'dns.resolver.NoAnswer'> The DNS response does not contain an answer to the question: _acme-challenge.zonetransfer.me. IN A

Results for nsztm2.digi.ninja. 
Zone origin: zonetransfer.me
---------------------------------------------------------------------------

Results for nsztm2.digi.ninja. 
Zone origin: zonetransfer.me
---------------------------------------------------------------------------
[*]  Error: <class 'dns.resolver.NoAnswer'> The DNS response does not contain an answer to the question: _acme-challenge.zonetransfer.me. IN A

Выполнить 2 без изменения кода (zonetransfer.me)

Attempting zone transfers for zonetransfer.me
Traceback (most recent call last):
  File "/home/kali/Exercises/Module_7/dns-axfer.py", line 56, in zoneXFR
    zone = dns.zone.from_xfr(dns.query.xfr(str(server).rstrip('.'), domain))
  File "/usr/lib/python3/dist-packages/dns/zone.py", line 1106, in from_xfr
    for r in xfr:
  File "/usr/lib/python3/dist-packages/dns/query.py", line 596, in xfr
    _net_write(s, tcpmsg, expiration)
  File "/usr/lib/python3/dist-packages/dns/query.py", line 364, in _net_write
    current += sock.send(data[current:])
ConnectionRefusedError: [Errno 111] Connection refused

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/kali/Exercises/Module_7/dns-axfer.py", line 73, in <module>
    zoneXFR()
  File "/home/kali/Exercises/Module_7/dns-axfer.py", line 66, in zoneXFR
    print ("\nResults for",server, "\nZone origin:", str(zone.origin).rstrip('.'))
UnboundLocalError: local variable 'zone' referenced before assignment

Мой сценарий: bash прочь ... Я всегда могу принять конструктивную критику.

#!/usr/bin/python3

import sys, argparse
import dns.query
import dns.zone
import dns.resolver
from colorama import Fore, Style

bracket = f"{Fore.BLUE}[{Fore.GREEN}*{Fore.BLUE}]{Style.RESET_ALL} "
bracket_err = f"{Fore.BLUE}[{Fore.RED}*{Fore.BLUE}]{Style.RESET_ALL} "
'''
parser = argparse.ArgumentParser()
parser.add_argument('domain')
args = parser.parse_args()
'''
# domain = (sys.argv[1])
domain = 'megacorpone.com'
#domain = 'zonetransfer.me'

def line():
    print ('-' * 75)
    return None

def resolveDNS(system):
    resolver = dns.resolver.Resolver()
    results = resolver.query(system , "A")
    return results

def getNS ():
    name_servers = dns.resolver.query(domain, 'NS')
    print ("\nThe name servers for " + domain + " are:")
    line()
    for system in name_servers:
        A_records = resolveDNS(str(system))
        for item in A_records:
            answer = ','.join([str(item)])
        print (bracket, "{:30}".format(str(system).rstrip('.')), "{:15}".format(answer))
    return name_servers

def getMX():
    mail_server = dns.resolver.query(domain, 'MX')
    print("\nMail servers for", domain)
    line()    
    for system in mail_server:
        A_records = resolveDNS(str(system.exchange))
        for item in A_records:
            answer = ','.join([str(item)])          
        print(bracket, "{:30}".format(str(system.exchange).rstrip('.')), "{:15}".format(str(answer)), '\t', "{:5}".format("Preference:"), str(system.preference))
    return None

def zoneXFR():
    print ("\nAttempting zone transfers for", domain,)

    for server in name_servers:
        try:
            zone = dns.zone.from_xfr(dns.query.xfr(str(server).rstrip('.'), domain))
            print ("\nResults for",server, "\nZone origin:", str(zone.origin).rstrip('.'))
            line()
            for host in zone:
                if str(host) != '@':
                    A_records = resolveDNS(str(host) + "." + domain)
                    for item in A_records:
                        answer = ','.join([str(item)])   
                    print(bracket, "{:30}".format(str(host) + "." + domain), answer)
        except Exception as e:
            print ("\nResults for",server, "\nZone origin:", str(zone.origin).rstrip('.'))
            line()
            print (bracket_err, f"{Fore.RED}Error:{Style.RESET_ALL}", e.__class__, e)


name_servers = getNS()
getMX()
zoneXFR()
print("\n")

1 Ответ

2 голосов
/ 22 марта 2020

Я вижу, что вы пробуете хорошо известные серверы имен, специально настроенные для тестирования. Однако для удобства других читателей я добавлю несколько объяснений.

Как вы, наверное, знаете, большинство серверов имен в настоящее время не разрешают передачу зон. При этом, возможно, что каждый из серверов имен для данного доменного имени будет вести себя по-разному (они могут иметь разные конфигурации и даже запускать различное программное обеспечение).

В случае megacorpone.com есть В списке 3 сервера имен:

  • ns2.megacorpone.com.
  • ns3.megacorpone.com.
  • ns1.megacorpone.com.

ns2.megacorpone.com - единственный, кто разрешил передачу зоны.

Это сообщение

dns.query.TransferError: Zone transfer error: REFUSED

означает, что оно означает: ваш запрос был отклонен. Возможно, вы говорили с неправильным сервером имен.

Затем у вас есть еще одна ошибка, которая предлагает проблему с изменяемой областью видимости:

UnboundLocalError: local variable 'zone' referenced before assignment

Вы вызываете функции в следующем порядке:

name_servers = getNS()
getMX()
zoneXFR()

Если name_servers завершится неудачно, последующий вызов zoneXFR также не удастся. Поскольку этот код:

for server in name_servers:

попытается выполнить итерацию по пустому списку.

Периодические сбои разрешения DNS распространены, поэтому здесь необходимо выполнить несколько проверок. По крайней мере, убедитесь, что список NS не пуст.

Другая проблема: вы запускаете for l oop вне блока try, поэтому ваша структура управления нарушается прямо в середина:

for server in name_servers:
    try:
        zone = dns.zone.from_xfr(dns.query.xfr(str(server).rstrip('.'), domain))
        print ("\nResults for",server, "\nZone origin:", str(zone.origin).rstrip('.'))
        line()

Сделайте это вместо:

try:
    for server in name_servers:
        zone = dns.zone.from_xfr(dns.query.xfr(str(server).rstrip('.'), domain))
        print ("\nResults for",server, "\nZone origin:", str(zone.origin).rstrip('.'))
        ...

Я подозреваю, что ваш скрипт прерывается периодически, потому что список серверов имен не всегда возвращается в одном и том же порядке . Если первый NS вернулся, ns1.megacorpone.com. или ns3.megacorpone.com. тогда код вылетает. Если сценарии начинаются с ns2.megacorpone.com (единственный NS, разрешающий перенос зон), значит, он работает нормально.

Когда этот код не работает (AXFR запрещен):

zone = dns.zone.from_xfr(dns.query.xfr(str(server).rstrip('.'), domain))

, тогда zone не определено, и поэтому вы не можете распечатать его в своем блоке исключений. Вместо этого покажите имя домена или некоторые другие переменные, которые, как вы знаете, определены и действительны.

Поэтому, если AXFR отклонен, ваш сценарий должен обработать это исключение dns.query.TransferError , и спокойно переходите к следующему NS, если таковой имеется, до тех пор, пока список не будет исчерпан.

Еще один совет: вы пытаетесь разрешить имена ресурсов, отличные от '@'. Вместо этого посмотрите на тип записи . Вы должны разрешить только CNAME, MX или NS. Другими распространенными типами являются TXT, A, AAAA, SOA. Остальные - более экзотические c, такие как NAPTR, LOC или SRV. Думаю, ничего не решено.

...