MichaCo / DnsClient.NET

DnsClient.NET is a simple yet very powerful and high performant open source library for the .NET Framework to do DNS lookups
https://dnsclient.michaco.net
Apache License 2.0
781 stars 137 forks source link

New Feature: Parallel DNS lookups #78

Open sdcarpenter opened 4 years ago

sdcarpenter commented 4 years ago

If a user has multiple DNS servers and one of those servers in inaccessible, they shouldn't have to wait for the down server to fail before trying the next one.

This is particularly important for users of OpenVPN who leverage the block-outside-dns option in their configuration. OpenVPN implements this by blocking all DNS servers but the one specified by the VPN Server. This in turn means that queries will timeout until that server is tried.

MichaCo commented 4 years ago

Sorry for the late reply.

I actually had a feature to dis-/en-able servers over time, basically disabling a server from the list of servers if it returns certain errors and then checking it again after a while.

The code to do that was just pretty hard to test and I didn't really want to make the whole query part more complex as necessary... That's why I remove that "feature".

I wasn't aware of that particular use-case in OpenVPN setups. That sounds pretty bad though and more like a hack of OpenVPN's implementation. If it block all calls, then why does it not close the socket / connection attempt right away?

I guess I have to take a closer look of how that really works, if you have more information or a simple setup to reproduce in a container or something, let me know

sdcarpenter commented 4 years ago

My turn to apologize for the late reply. I did a bit of digging into the OpenVPN client to understand exactly what they are doing. We use OpenVPN to connect to our AWS virtual private cloud, and leverage a split-horizon DNS setup so that internal backend interfaces will resolve correctly when connected to the VPN, and resolve to the public interfaces when not. To make this work with OpenVPN we use a flag called "block-outside-dns". This is supposed to prevent DNS leaks when connected to the VPN and ensure that the computer connected to the VPN will only use the DNS server the VPN instructs it to.

I believe that the Windows 10 resolver will send DNS requests out to all DNS servers it knows about in the system, and return with the fastest answer (ignoring errors in slower responses, and also resulting in non-deterministic answers to DNS queries if DNS information is not consistent). It looks like the OpenVPN client achieves it's DNS blocking by leveraging the Windows Filtering Platform, and I believe what it is doing, is just dropping any UDP packets sent to all DNS servers other than the one provided by the VPN (thus if DnsClient.NET selects a blocked server first, it'll get a timeout, then try the unblocked one and give an answer).

Your suggestion solution is a good one, although you could start out with a slow DNS lookup at first. The other option would be to operate like the Windows 10 resolver and let the queries "race".

All that being said, we've worked around the issue, so it may not be worth the added complexity. But perhaps this ticket will help someone else who encounters the same thing we did.