-
-
Notifications
You must be signed in to change notification settings - Fork 138
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
LookupClient.QueryAsync is not concurrency-safe #209
Comments
Hi @sengelha, That being said, because of the limitation for min/max value being between 0 and 65535, collisions could still occur in theory. After reading a bit how the request identifier is supposed to be used I found that the Id is not supposed to be used alone to route a response. The server is supposed to use the source port plus the id. I tested that locally with using bind or some public DNS servers, sending 10 queries in parallel in a loop, all queries with the same hardcoded ID (not random); and I did not see any issues at all. Could you tell me what DNS server you are using or if that is a custom implementation which might not respect the source port properly? Maybe that explains why you see that behavior. |
Thanks @MichaCo (btw library is great other than this obscure bug, thank you) Something I didn't mention above. In order to reproduce, I had to disable DnsClient lookup caching ( I am running my tests from a Windows 10 Version 22H2 (OS Build 19045.3930) machine. The DNS server is my corporate intranet DNS server, which I would guess is our Active Directory domain server, but I don't know for sure. FWIW, not using request id alone and using source port + id instead seems even more sensible to me. |
* better impl for TCP connection timeouts
Summary
In DnsClient 1.7.0,
LookupClient.QueryAsync
is not concurrency-safe. If an application issues two concurrent requests to lookup DNS names A and B, the request to lookup A may return the result from the lookup of B because they can share the same DNS request unique id.How to Reproduce
At work we have a number of DNS TXT records which we use for service discovery purposes. We determined, by connecting to the DnsClient internal logger, that two
DnsRequestHeader
s were generated with identical query ids, and the response for request B was delivered to a request A. The fact that the DNS TXT record may be a few hundred bytes and the response may take more than a trivial amount of time to deliver likely makes this bug easier to observe.I tried to reproduce the bug by writing a program doing CNAME lookups of popular public domain names but I was unable to do so.
Here are some sample log records from the repro, with some fields replaced with placeholders:
Root Cause
The class
DnsRequestHeader
uses a staticRandom
instance to generate query ids. ThisRandom
instance is not concurrency-safe, which means that two threads which simultaneously constructDnsRequestHeader
can result generate the same unique 16-bit request identifier in the methodDnsRequestHeader.GetNextUniqueId()
. If DNS requests A and B happen to generate the same unique request identifier, the response for DNS request B may be delivered to DNS request A.Suggested Fix
Random.Shared
instead ofnew Random()
, asRandom.Shared
is a thread-safe Random instance.The text was updated successfully, but these errors were encountered: