dnspython icon indicating copy to clipboard operation
dnspython copied to clipboard

Timout in async and sync DoH query

Open fleurysun opened this issue 2 years ago • 4 comments

Sometimes timeout in dns.asyncquery.https and dns.query.https doesn't work as expected, when querying server 75.119.137.220, which in fact isn't a DoH server, it will never timeout, it will hang at calling the_client.get or the_client.post method.

To Reproduce:

import asyncio
import dns.message
import dns.asyncquery
import dns.rdatatype

async def check_doh(ip, query_name, timeout):
    query = dns.message.make_query(query_name, dns.rdatatype.A)
    response = await dns.asyncquery.https(query, ip, verify=False, timeout=timeout)
    print(response)

if __name__ == "__main__":
    asyncio.run(check_doh("75.119.137.220", "dnspython.org", 6))

System info:

  • dnspython version [2.5.0]
  • Python version [3.10.12]
  • OS version [CentOS 7.8.2003]

fleurysun avatar Aug 07 '23 08:08 fleurysun

This one seems to be a limitation in the way timeouts work in httpx/httpcore. I'm seeing the correct timeout value get passed into httpcore, but the API only has the concept of individual operation timeouts. I see it trying to get the body of the response, and constantly reading 16KiB chunks of data, and this seems to go on for some time, certainly longer than the 6 second lifetime timeout we would like.

I am not sure how to fix this for the sync API, but for async I can fix it by limiting how long we wait for the future. E.g. if I do this:

async def check_doh(ip, query_name, timeout):
    query = dns.message.make_query(query_name, dns.rdatatype.A)
    response = await asyncio.wait_for(dns.asyncquery.https(query, ip, verify=False), timeout)
    print(response)

it returns after 6 seconds. I can move that kind of logic into dns.asyncquery.https().

rthalley avatar Aug 07 '23 13:08 rthalley

Thank you! Yep, the httpx API timeouts aren't fully supported, as mentioned in encode/httpx#2658

fleurysun avatar Aug 08 '23 07:08 fleurysun

I'm leaving this ticket open so we remember to fix this for sync if httpx gives us a way to do so in the future. I made fixes for asyncio and trio, and they were included in the 2.4.2 release.

rthalley avatar Aug 12 '23 20:08 rthalley