CNAME resolve_chain

549 views
Skip to first unread message

Arvind Doraiswamy

unread,
Aug 13, 2022, 5:11:04 PM8/13/22
to dnspython-users
Hi,
Could you help me with an example of using resolve_chain() to query an entire CNAME chain?

For e.g.

results = dns.resolver.resolve(DOMAIN, 'CNAME')

and if that returns a CNAME A which points to CNAME B which points to CNAME C...which points to a set of ips [IP1, IP2], how do I get that set?

I looked at the tests here, but even using make_query() and forming the query by hand did not work. As in when I printed out result.answer it said 'None' which was obviously wrong..

and so I'm not sure how to make this work? thoughts?

Thanks
Arvind

Bob Halley

unread,
Aug 13, 2022, 6:09:52 PM8/13/22
to dnspython-users
The resolver automatically calls chaining_result for you, so ask for the type you really want, e.g. type A.  Let's look at www.dnspython.org, which CNAMEs to a cloudfront name:

>>> import dns.resolver

>>> answer = dns.resolver.resolve('www.dnspython.org', 'A')

# Just iterate the answer to get the A records:

>>> for rr in answer:

...   print(rr)

... 

13.35.125.90

13.35.125.81

13.35.125.88

13.35.125.115

# If you want to look at all the CNAMEs you went through (if any)

>>> print(answer.chaining_result.cnames)

[<DNS www.dnspython.org. IN CNAME RRset: [<dmfrjf4ips8xa.cloudfront.net.>]>]

# The canonical name is the last name in the CNAME chain, if you chained, or the name you queried if you didn't chain:

>>> print(answer.chaining_result.canonical_name)

dmfrjf4ips8xa.cloudfront.net.



Arvind Doraiswamy

unread,
Aug 14, 2022, 1:51:05 PM8/14/22
to dnspython-users
This is such a great answer and exactly what I wanted. Thank you so much :)

Arvind Doraiswamy

unread,
Aug 14, 2022, 2:06:37 PM8/14/22
to dnspython-users
I guess a follow up question as well - in case one of the CNAMES in the chain is dead and doesn't resolve, will resolve() automatically throw a NXDOMAIN, or do I need to query each CNAME separately and find ot if it exists?

Bob Halley

unread,
Aug 14, 2022, 4:02:56 PM8/14/22
to dnspython-users
If one of the CNAMEs points at a name which fails to resolve,  the full resolver you're talking to will send a SERVFAIL response or not respond in time.  You will end up with a NoNameservers exception or a LifetimeTimeout exception depending on the setting of resolver.retry_servfail, whether the server responds at all, and if so, how long it takes.

dnspython is a stub resolver, so it either gets the whole answer or nothing, so if you wanted to find out whether you got the SERVFAIL due to a CNAME problem, you'd have to investigate that hop-by-hop by making CNAME queries.

Note that above I didn't consider two other things that can happen with a CNAME chain, namely

1) The chain ends in a name which resolves as NXDOMAIN.  In this case you'll get an NXDOMAIN exception.
2) The chain ends in a name which resolves as no-error, no-data, i.e. "the name exists but no data of the type you requested exists at that name".  In this case you'll get a NoAnswer exception or an empty answer rrset if you have raise_on_no_answer set to False.

Arvind Doraiswamy

unread,
Aug 14, 2022, 8:58:39 PM8/14/22
to dnspython-users
Great, thank you very much for that detailed answer.
Reply all
Reply to author
Forward
0 new messages