【问题标题】:How do we get TXT, CNAME and SOA records from dnspython?我们如何从 dnspython 获取 TXT、CNAME 和 SOA 记录?
【发布时间】:2012-11-30 07:06:39
【问题描述】:

我需要有一个 dns 查询功能来查询服务器的各种记录。我想出了如何获取 MX 记录(大多数示例都显示了这一点)、A 记录和 NS 记录。如何获取 TXT、CNAME 和 SOA 记录?

示例代码sn-p:

   import dns.resolver
   answer=dns.resolver.query("google.com", "A")
       for data in answer:
           print data.address

我尝试用 TXT 替换查询类型,用 data.text、data.data 等替换 data.address 对象,但最终出现属性错误。我前面提到的数据类型有哪些参考?

【问题讨论】:

    标签: python dns dnspython


    【解决方案1】:

    (回答如何计算返回的数据)

    您可以通过类似的方式获取 TXT、CNAME 和 SOA 记录,但您只需要根据 DNS 响应对象获取正确的属性。

    使用内置的 python dir() 是您的朋友,也是一种确定 DNS 响应对象中存在哪些属性的方法 - 当 API 文档不可用时很方便。

    要找出适当的属性,请将您的 for 循环暂时更改为以下内容:

       for data in answer:
           print dir(data)
           print data
    

    另一种更快的方法是查看 dnspython 的 API 文档,这些页面列出了每个返回对象的属性。

    最后,如果库在 python 中,您可以查看源代码,如果不是,则 C 代码是否可用。

    (并回答你的问题:)

    以下是 TXT、CNAME 和 SOA 查询示例:

    TXT

    http://www.dnspython.org/docs/1.15.0/dns.rdtypes.txtbase.TXTBase-class.html#section-InstanceVariables

    answers = dns.resolver.query('google.com', 'TXT')
    print ' query qname:', answers.qname, ' num ans.', len(answers)
    for rdata in answers:
        for txt_string in rdata.strings:
          print ' TXT:', txt_string
    

    CNAME

    http://www.dnspython.org/docs/1.15.0/dns.rdtypes.ANY.CNAME.CNAME-class.html

    answers = dns.resolver.query('mail.google.com', 'CNAME')
    print ' query qname:', answers.qname, ' num ans.', len(answers)
    for rdata in answers:
        print ' cname target address:', rdata.target
    

    SOA

    http://www.dnspython.org/docs/1.15.0/dns.rdtypes.ANY.SOA.SOA-class.html#section-InstanceVariables

    answers = dns.resolver.query('google.com', 'SOA')
    print 'query qname:', answers.qname, ' num ans.', len(answers)
    for rdata in answers:
        print ' serial: %s  tech: %s' % (rdata.serial, rdata.rname)
        print ' refresh: %s  retry: %s' % (rdata.refresh, rdata.retry)
        print ' expire: %s  minimum: %s' % (rdata.expire, rdata.minimum)
        print ' mname: %s' % (rdata.mname)
    

    【讨论】:

    • 注意事项:防御性编程,无论您要求什么记录类型,不要期望默认返回您要求的内容,在尝试使用之前始终检查您返回的记录类型以某种方式。
    【解决方案2】:

    你可以尝试一些不同的东西。

    您可以对任何记录进行一次查询,而不是每次都查询每个记录类型。 这样,如果该域同时具有 TXT、CNAME 等...您将获得一个包含所有数据的对象。

    from dns.resolver import dns
    name_server = '8.8.8.8' #Google's DNS server
    ADDITIONAL_RDCLASS = 65535
    request = dns.message.make_query('google.com', dns.rdatatype.ANY)
    request.flags |= dns.flags.AD
    request.find_rrset(request.additional, dns.name.root, ADDITIONAL_RDCLASS,
                           dns.rdatatype.OPT, create=True, force_unique=True)       
    response = dns.query.udp(request, name_server)
    

    希望这对您有所帮助。

    【讨论】:

    • 你为什么要指定ADDITIONAL_RDCLASS = 65535 我已经看过了,但找不到太多关于它的作用。
    • 您不必这样做。它只是为了涵盖所有可能的记录类型 ID。通常使用 2 的幂来表示,目前最大的 ID 是 32769 (DLV)。这需要 2^16(2^15 是 32768)
    • 不,不要这样做ANY。与普遍的理解相反,它 NOTALL 的同义词,它只会为您提供缓存内容中的内容,当然不是所有记录(取决于其活动)。此外,这已经被过滤,并且 IETF 中有一些作品只是渲染 ANY 过时。所以无论你的问题是什么,ANY 都不是你的解决方案。
    • 至于“如果该域同时具有 TXT、CNAME”:根据定义,任何单个域名的 CNAME 记录不能与任何其他记录共存。
    • 实际上,在添加 OPT 伪 RR 时,CLASS 字段指定请求者的 UDP 有效负载大小:datatracker.ietf.org/doc/html/rfc6891#section-6.1 这意味着您必须确保您的网络堆栈可以重组/传递 UDP 消息这个大小的。 RFC 建议将 4096 作为一个很好的折衷方案。
    【解决方案3】:

    以以前的答案为例,创建 dnsdig.py 文件:

    import sys
    import socket
    import dns.resolver
    
    print 'Argument List:', str(sys.argv)
    site = sys.argv[1]
    dns_server = sys.argv[2]
    
    # Basic CNAME query the host's DNS
    for rdata in dns.resolver.query(site, 'CNAME') :
        print rdata.target
    
    # Basic A query the host's DNS
    for rdata in dns.resolver.query(site, 'A') :
        print rdata.address
    
    # Setting an specific DNS Server
    resolver = dns.resolver.Resolver()
    resolver.nameservers = [socket.gethostbyname(dns_server)]
    
    # Basic CNAME query with the specific DNS server
    answer = resolver.query(site, 'CNAME');
    for rdata in answer :
        print rdata.target
    
    # Basic A query with the specific DNS server
    answer = resolver.query(site, 'A');
    for rdata in answer :
        print rdata.address
    

    运行:

    python dnsdig.py www.youtube.com 8.8.8.8
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-06
      • 2013-03-21
      • 2014-06-11
      • 1970-01-01
      • 2012-12-29
      相关资源
      最近更新 更多