为什么 DNSPython 区域传输偶尔会失败
Why is DNSPython zone transfer sporadically failing
所以,在 python 方面,我仍然处于菜鸟级别。我知道......我知道......可能有更有效的方法来做我正在尝试但仍在学习的事情,希望我会通过练习变得更好。
对于一个培训项目,我正在编写一个脚本来对域执行各种 DNS 操作。我找到了 DNSPython,它似乎正是我需要使用的东西,我以为我已经完成了它,但是当我针对不同的域尝试它时,它在区域传输时总是失败。
我现在有两个硬编码的域用于测试。 megacorpone 域 iw 按照我的预期工作,但是现在它失败了(没有代码更改)为了让它工作我必须过滤返回的第一条记录“@”否则它也会失败。
然而,zonetransfer.me 域有时会在完成脚本时出现错误,但偶尔也会失败,但由于某种原因它从不显示主机记录,我一直无法弄清楚如何修复还没有,我已经用脑袋撞了一段时间了。
megacoprone 运行 之前每次都在工作,现在它根本不工作了。目前我唯一能想到的可能是时间问题。
运行 与 megacoprpone
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")
我看到您正在尝试专门为测试设置的知名名称服务器。但是,为了其他读者的利益,我将添加一些解释。
您可能已经知道,现在大多数名称服务器都不允许区域传输。也就是说,给定域名的每个名称服务器可能会有不同的行为(它们可能有不同的配置,甚至是 运行 不同的软件)。
在 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列表不为空
另一个问题:您在 try
块之外启动了一个 for
循环,因此您的控制结构在中间被破坏了:
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))
then zone
没有定义,这就是为什么你不能在你的异常块中打印它。相反,显示域名或您知道已定义且有效的其他一些变量。
因此,如果 AXFR 被拒绝,您的脚本应该处理此异常 dns.query.TransferError,并悄悄地转移到下一个 NS(如果有的话),直到列表被耗尽。
另一点建议:您尝试解析与“@”不同的资源名称。相反,请查看 记录类型 。您应该只解析 CNAME
、MX
或 NS
。其他常见的类型有TXT
、A
、AAAA
、SOA
。其余的更奇特,例如 NAPTR
、LOC
或 SRV
。我认为没有什么应该解决的。
已修复您的代码,虽然看起来不太好,但可以正常工作
#!/usr/bin/python3
# you might want to run python3 -m pip install dnspython before running this script
import sys
import dns.query
import dns.zone
import dns.resolver
# formatting setup
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} "
def drawLine():
print ('-' * 75)
# read arguments
try:
domain = (sys.argv[1])
except:
print("[!] USAGE: python3 zt.py DOMAIN_NAME")
sys.exit(0)
# DNS functions
def resolveDNS(name):
resolver = dns.resolver.Resolver()
results = resolver.query(name , "A")
return results
def getNS (domain):
mapping = {}
name_servers = dns.resolver.query(domain, 'NS')
print ("\nThe name servers for " + domain + " are:")
drawLine()
for name_server in name_servers:
A_records = resolveDNS(str(name_server))
for item in A_records:
answer = ','.join([str(item)])
mapping[str(name_server)] = answer
print (bracket, "{:30}".format(str(name_server).rstrip('.')), "{:15}".format(answer))
return mapping
def zoneXFR(server):
try:
zone = dns.zone.from_xfr(dns.query.xfr(str(server).rstrip('.'), domain))
except Exception as e:
print (bracket_err, f"{Fore.RED}Error:{Style.RESET_ALL}", e.__class__, e)
else:
print ("\nResults for",server, "\nZone origin:", str(zone.origin).rstrip('.'))
drawLine()
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)
drawLine()
name_servers = getNS(domain)
for server in name_servers:
print ("\nAttempting zone transfers for", server,name_servers[server])
zoneXFR(name_servers[server])
所以,在 python 方面,我仍然处于菜鸟级别。我知道......我知道......可能有更有效的方法来做我正在尝试但仍在学习的事情,希望我会通过练习变得更好。
对于一个培训项目,我正在编写一个脚本来对域执行各种 DNS 操作。我找到了 DNSPython,它似乎正是我需要使用的东西,我以为我已经完成了它,但是当我针对不同的域尝试它时,它在区域传输时总是失败。
我现在有两个硬编码的域用于测试。 megacorpone 域 iw 按照我的预期工作,但是现在它失败了(没有代码更改)为了让它工作我必须过滤返回的第一条记录“@”否则它也会失败。
然而,zonetransfer.me 域有时会在完成脚本时出现错误,但偶尔也会失败,但由于某种原因它从不显示主机记录,我一直无法弄清楚如何修复还没有,我已经用脑袋撞了一段时间了。
megacoprone 运行 之前每次都在工作,现在它根本不工作了。目前我唯一能想到的可能是时间问题。
运行 与 megacoprpone
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")
我看到您正在尝试专门为测试设置的知名名称服务器。但是,为了其他读者的利益,我将添加一些解释。
您可能已经知道,现在大多数名称服务器都不允许区域传输。也就是说,给定域名的每个名称服务器可能会有不同的行为(它们可能有不同的配置,甚至是 运行 不同的软件)。
在 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列表不为空
另一个问题:您在 try
块之外启动了一个 for
循环,因此您的控制结构在中间被破坏了:
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))
then zone
没有定义,这就是为什么你不能在你的异常块中打印它。相反,显示域名或您知道已定义且有效的其他一些变量。
因此,如果 AXFR 被拒绝,您的脚本应该处理此异常 dns.query.TransferError,并悄悄地转移到下一个 NS(如果有的话),直到列表被耗尽。
另一点建议:您尝试解析与“@”不同的资源名称。相反,请查看 记录类型 。您应该只解析 CNAME
、MX
或 NS
。其他常见的类型有TXT
、A
、AAAA
、SOA
。其余的更奇特,例如 NAPTR
、LOC
或 SRV
。我认为没有什么应该解决的。
已修复您的代码,虽然看起来不太好,但可以正常工作
#!/usr/bin/python3
# you might want to run python3 -m pip install dnspython before running this script
import sys
import dns.query
import dns.zone
import dns.resolver
# formatting setup
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} "
def drawLine():
print ('-' * 75)
# read arguments
try:
domain = (sys.argv[1])
except:
print("[!] USAGE: python3 zt.py DOMAIN_NAME")
sys.exit(0)
# DNS functions
def resolveDNS(name):
resolver = dns.resolver.Resolver()
results = resolver.query(name , "A")
return results
def getNS (domain):
mapping = {}
name_servers = dns.resolver.query(domain, 'NS')
print ("\nThe name servers for " + domain + " are:")
drawLine()
for name_server in name_servers:
A_records = resolveDNS(str(name_server))
for item in A_records:
answer = ','.join([str(item)])
mapping[str(name_server)] = answer
print (bracket, "{:30}".format(str(name_server).rstrip('.')), "{:15}".format(answer))
return mapping
def zoneXFR(server):
try:
zone = dns.zone.from_xfr(dns.query.xfr(str(server).rstrip('.'), domain))
except Exception as e:
print (bracket_err, f"{Fore.RED}Error:{Style.RESET_ALL}", e.__class__, e)
else:
print ("\nResults for",server, "\nZone origin:", str(zone.origin).rstrip('.'))
drawLine()
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)
drawLine()
name_servers = getNS(domain)
for server in name_servers:
print ("\nAttempting zone transfers for", server,name_servers[server])
zoneXFR(name_servers[server])