dnspython中的服务器名称可达性

2024-06-01 04:43:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正试图找到一种方法来检查名称服务器是否可以响应TCP或UDP数据包

我的想法是,从一个网站(例如google.com)获取所有名称服务器,将它们存储在一个列表中,然后尝试向所有服务器发送TCP和UDP消息

虽然我得到了名称服务器,但当我试图对udp进行查询时(检查代码上的udpPacket),我的解释器显示出一个问题,它说:

"TypeError: coercing to Unicode: need string or buffer, NS found"

我是Python新手(来自C和C++),我猜这只是不兼容的类型

我检查了dnspython的文档,找不到NS是什么类型的(可能它本身就是一个类型),也找不到为什么它不能作为参数传递

你认为问题是什么?有没有更好的办法来解决这类问题

def getNSResults(url):

    #create an empty list where we can store all the nameservers we found
    nameServers = []

    nameServers = dns.resolver.query(url,dns.rdatatype.NS, raise_on_no_answer=False)

    #create a dictionary where based on all the nameservers.
    #1st label refers to the ns name of our url that we inserted.
    #2nd label shows wether or not we received a UDP response or not.
    #3rd label shows wether or not we received a TCP response or not.
    results = {}

    for nameServer in nameServers:

        #make a dns ns query, acts as a dumb message since whatever we send we just care of what we get back
        query = dns.message.make_query(dns.name.from_text(url), dns.rdatatype.ANY)

        query.flags |= dns.flags.AD

        query.find_rrset(query.additional, dns.name.root, 65535, dns.rdatatype.OPT, create=True, force_unique=True)

        #try sending a udp packet to see if it's listening on UDP
        udpPacket = dns.query.udp(query,nameServer)

        #try sending a tcp packet to see if it's listening on TCP
        tcpPacket = dns.query.tcp(None,nameServer)

        #add the results in a dictionary and return it, to be checked later by the user.
        results.update({"nsName" == nameServer, "receivedUDPPacket" == isNotNone(udpPacket),"receivedTCPPacket" == isNotNone(tcpPacket)})

提前谢谢


Tags: ortheto服务器名称urlondns
1条回答
网友
1楼 · 发布于 2024-06-01 04:43:07

查看您的代码,我看到一些DNS问题、一些Python问题和一些dnspython问题。让我们看看我们能不能一起学点东西

域名系统

首先,函数getNSResults的参数称为url。当您发送DNS查询时,您需要查询一个域名。URL是完全不同的(例如https://example.com/index.html)。我会将url重命名为类似domain_namedomainname的名称。有关URL和域名之间差异的更多信息,请参见https://www.copahost.com/blog/domain-vs-url/

第二,让我们谈谈你想做什么

i am currently trying to find a way to check wether or not the name servers can respond to either tcp or udp packets.

My idea behind that was, to get all the name servers from a website (for example google.com), store them in a list, and then, try to send tcp and udp messages to all of them.

这听起来是个不错的方法。我想你可能遗漏了一些细节。因此,让我解释一下您可以采取的步骤:

  1. 对域名执行NS查询。您的代码中已包含此步骤。从该查询中实际得到的只是另一个域名(或多个域名)。例如,如果运行dig +short NS google.com,将获得以下输出:
ns3.google.com.
ns1.google.com.
ns4.google.com.
ns2.google.com.
  1. 在这一步中,我们有一个权威服务器的一个或多个名称的列表。现在我们需要一个IP地址来向他们发送查询。因此,我们将对从步骤1中获得的每个名称进行类型a查询
  2. 现在我们有一个IP地址列表。我们可以通过UDP发送一个DNS查询,通过TCP发送一个DNS查询,看看它们是否受支持

Python

在大多数情况下,您的Python语法是正确的。 我看到的最大的危险是以下代码:

results.update({"nsName" == nameServer, 
    "receivedUDPPacket" == isNotNone(udpPacket),
    "receivedTCPPacket" == isNotNone(tcpPacket)})

让我们把它分解一下。 首先,您有results,这是一个dict。 那么你有这个:

{"nsName" == nameServer, 
"receivedUDPPacket" == isNotNone(udpPacket),
"receivedTCPPacket" == isNotNone(tcpPacket)}

这是{}的{}。 我想你的意思是这样的:

results.update({
    "nsName": nameServer,
    "receivedUDPPacket": true,
    "receivedTCPPacket": true
})

Python中的函数和变量名称通常用小写字母书写,单词之间用下划线分隔(例如my_variabledef 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是一些非常有用和有趣的东西

我继续写了一些东西,这是我认为你们希望实现的目标的开始。 我建议你从头到尾走一遍,确保你明白发生了什么。 如果你不懂一些东西,记得pdbdir(还有谷歌,等等)

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()

我再次希望这是有帮助的。当我不知道你脑子里到底在想什么的时候很难,但这就是我为你准备的

相关问题 更多 >