查看您的代码,我看到一些 DNS 问题、一些 Python 问题和一些 dnspython 问题。让我们看看我们是否可以一起学习一些东西。
域名系统
首先,getNSResults
调用函数的参数url
。当您发送 DNS 查询时,您查询的是域名。URL 是完全不同的东西(例如https://example.com/index.html
)。我会重命名url
为domain_name
,domain
或name
. 有关 URL 和域名之间区别的更多信息,请参阅https://www.copahost.com/blog/domain-vs-url/。
其次,让我们谈谈你想要做什么。
我目前正在尝试找到一种方法来检查名称服务器是否可以响应 tcp 或 udp 数据包。
我的想法是,从网站(例如 google.com)获取所有名称服务器,将它们存储在一个列表中,然后尝试向所有这些服务器发送 tcp 和 udp 消息。
这听起来是一个很好的方法。我想你可能在这里遗漏了一些细节。所以让我解释一下你可以采取的步骤:
- 对域名进行 NS 查询。您的代码中已经包含此步骤。您实际上从该查询中得到的只是另一个域名(或多个域名)。例如,如果您运行
dig +short NS google.com
,您将获得以下输出:
ns3.google.com.
ns1.google.com.
ns4.google.com.
ns2.google.com.
- 在这一步,我们有一个或多个权威服务器名称的列表。现在我们需要一个 IP 地址来向他们发送查询。因此,我们将对从步骤 1 中获得的每个名称进行 A 类查询。
- 现在我们有了一个 IP 地址列表。我们可以通过 UDP 和 TCP 发送一个 DNS 查询,看看它们是否受支持。
Python
在大多数情况下,您的 Python 语法是可以的。我看到的最大危险信号是以下代码:
results.update({"nsName" == nameServer,
"receivedUDPPacket" == isNotNone(udpPacket),
"receivedTCPPacket" == isNotNone(tcpPacket)})
让我们分解一下。首先,你有results
,这是一个dict
。然后你有这个:
{"nsName" == nameServer,
"receivedUDPPacket" == isNotNone(udpPacket),
"receivedTCPPacket" == isNotNone(tcpPacket)}
这是sset
的一个bool
。我认为你的意思是这样的:
results.update({
"nsName": nameServer,
"receivedUDPPacket": true,
"receivedTCPPacket": true
})
Python 中的函数和变量名称通常用小写字母书写,单词之间用下划线分隔(例如my_variable
, def my_function()
)。类名通常是大写的驼峰式(例如class MyClass
)。这些都不是必需的,你可以随心所欲地命名你的东西,许多超级流行的库和内置函数打破了这个约定,只是想我会把它扔在那里,因为它在阅读 Python 代码时会很有帮助。
dnspython
当您不确定事物的类型或事物具有哪些属性时,请记住这四个朋友,它们都是 Python 内置的:1. pdb
2. dir
3. type
4.print
pdb
是一个 Python 调试器。只是import pdb
, 和pdb.set_trace()
你想打破的地方。您的代码将停在那里,然后您可以检查所有变量的值。
dir
将返回您传递给它的任何属性和方法。示例:print(dir(udpPacket))
。
type
将返回对象的类型。
print
正如您可能已经知道的那样,它将打印出一些内容以便您查看。
我将把这部分留给你测试。dir()
如果您不知道它是什么,请运行所有内容。我还应该提一下help()
,这对于内置的东西非常有用。
本节的总结是,有时文档并不全部存在,或者很难找到,尤其是当您不熟悉语言/库/任何东西时。所以你必须自己解决问题,这意味着使用我刚才提到的所有工具,查看源代码,诸如此类。
概括
我希望这可以帮到你。我知道这很多,可能太多了,但请耐心等待,并知道 DNS 和 Python 是一些非常有用和有趣的东西,值得学习。
我继续写了一些东西,这是我认为您希望实现的目标的开始。我建议您浏览整个过程并确保您了解正在发生的事情。如果您不理解某些内容,请记住pdb
和dir
(并且总是有 Google、SO 等)。
import dns.resolver
import dns.message
import dns.rdatatype
import json
import sys
def check_tcp_and_udp_support(name):
# this will give me the first default system resolver from /etc/resolv.conf
# (or Windows registry)
where = dns.resolver.Resolver().nameservers[0]
q = dns.message.make_query(name, dns.rdatatype.NS)
ns_response = dns.query.udp(q, where)
ns_names = [t.target.to_text() for ans in ns_response.answer for t in ans]
# this code is the same as the one-liner above
# ns_names = []
# for ans in ns_response.answer:
# for t in ans:
# ns_names.append(t.target.to_text())
results = {}
for ns_name in ns_names:
# do type A lookup for nameserver
q = dns.message.make_query(ns_name, dns.rdatatype.A)
response = dns.query.udp(q, where)
nameserver_ips = [item.address for ans in response.answer for item in ans.items if ans.rdtype == dns.rdatatype.A]
# now send queries to the nameserver IPs
for nameserver_ip in nameserver_ips:
q = dns.message.make_query('example.com.', dns.rdatatype.A)
try:
udp_response = dns.query.udp(q, nameserver_ip)
supports_udp = True
except dns.exception.Timeout:
supports_udp = False
try:
tcp_response = dns.query.tcp(q, nameserver_ip)
supports_tcp = True
except dns.exception.Timeout:
supports_tcp = True
results[nameserver_ip] = {
'supports_udp': supports_udp,
'supports_tcp': supports_tcp
}
return results
def main():
results = check_tcp_and_udp_support('google.com')
# this is just fancy JSON printing
# you could do print(results) instead
json.dump(results, sys.stdout, indent=4)
if __name__ == '__main__':
main()
再次,我希望这会有所帮助。当我不知道你脑子里到底在想什么时,这很难,但这就是我为你准备的。