How do we get TXT, CNAME and SOA records from dnspython?
Asked Answered
I

3

19

I have a requirement to have a dns query function to query a server for various records. I figured out how to get the MX record (most of the examples show this), A record and NS record. How do I get the TXT, CNAME and SOA records?

Sample code snippet:

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

I tried replacing the query type with TXT and the data.address object with data.text, data.data etc, but ended up with attribute errors. What are the references for the data types I mentioned earlier?

Inhumation answered 12/12, 2012 at 14:42 Comment(0)
M
30

(To answer how you can figure out the returned data)

You can get the TXT, CNAME, and SOA records a similar way but you just have to get the correct attributes depending on the DNS response object.

Using the python dir() built-in is your friend and one way to figure out what attributes exist in the DNS response object - handy when API documentation is not available. To figure out the appropriate attributes, change your for loop temporarily to the following:

   for data in answer:
       print dir(data)

Another and quicker way is to look at the API documentation for dnspython, these pages list the attributes for each returned object.

Lastly, you could look at the source if the library is in python or if not, then if the C code is available.

(And to answer your question)

Here are examples of TXT, CNAME and SOA queries:

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)
Mindy answered 6/1, 2013 at 2:41 Comment(1)
Word of caution: to be programming defensively, whatever you ask as record type, do not expect by default to get back what you asked for, always check the record type you got back before trying to use it in some way.Revoke
H
12

You can try something a bit different.

Instead of querying each time per record type, you can make a single query for ANY record. This way if that domain has both TXT, CNAME etc... you'll get one object with all the data.

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)

Hope this might assist you.

Harriott answered 5/3, 2014 at 13:40 Comment(5)
Why do you specify ADDITIONAL_RDCLASS = 65535 I've looked & can't find much as to what this does.Pilarpilaster
You don't have to. it's merely to cover all possible Record Types ids. It's common to use powers of 2 to represent it, and as of now the largest ID is 32769 (DLV). which requires 2^16 (2^15 is 32768)Harriott
No, do not do ANY. Contrary to popular understanding, it is NOT a synonym of ALL it will give you only what the cache has in its content, certainly not all records (depending on its activity). Also this is already filtered and there are works in the IETF to just render ANY obsolete. So whatever your problem is, ANY is not your solution.Revoke
As for "if that domain has both TXT, CNAME" : a CNAME record can not coexist for any single domain name with any other records, by definition.Revoke
Actually, when adding an OPT pseudo-RR, the CLASS field specifies the requestor's UDP payload size: datatracker.ietf.org/doc/html/rfc6891#section-6.1 That means you have to make sure that your network stack can reassemble/deliver UDP messages of this size. The RFC suggest 4096 as a good compromise.Darkling
R
3

Exampling with a previous answer, create the dnsdig.py file with:

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

To run:

python dnsdig.py www.youtube.com 8.8.8.8
Riviera answered 12/2, 2017 at 20:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.