Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extremely slow resolution on Windows #1968

Open
NotNite opened this issue Jun 12, 2023 · 9 comments
Open

Extremely slow resolution on Windows #1968

NotNite opened this issue Jun 12, 2023 · 9 comments

Comments

@NotNite
Copy link

NotNite commented Jun 12, 2023

Describe the bug
On my machine, TokioAsyncResolver takes a very long time to resolve any DNS record - up to a minute! - regardless of domain, record type, or configured DNS servers in Windows. I don't even know why this is happening, because I can't actually repro it on my other machines - only on this specific Windows machine (Linux machines on same network work fine). I encountered this from a library I was using that depends on trust_dns_resolver. I'm mainly posting this in hopes that anyone has idea for better debugging steps so we can work it out together.

To Reproduce

use trust_dns_resolver::{proto::rr::RecordType, TokioAsyncResolver};

#[tokio::main]
async fn main() {
    let resolver = TokioAsyncResolver::tokio_from_system_conf().unwrap();
    let records = resolver.lookup("rust-lang.org", RecordType::A).await.ok();
    println!("{:?}", records);
}

Expected behavior
Not take 20.046 seconds to resolve rust-lang.org.

System:

  • OS: Windows 10
  • Architecture: x86_64
  • Version 22H2 (19045.2965)
  • rustc version: rustc 1.72.0-nightly (37998ab50 2023-06-11)

Version:
Crate: trust_dns_resolver
Version: 0.22.0

@djc
Copy link
Collaborator

djc commented Jun 12, 2023

Set up a basic tracing-subscriber to get a feel for which part is slow? Investigate what the system config amounts to on this system?

@bluejekyll
Copy link
Member

We've had other reports of trust-dns cycling through interfaces on Windows. We don't have a lot of folks contributing to the project from Windows, so it's sadly not as well supported as macOS and Linux. If you do have some time to investigate this, that would be really helpful to this project!

@mat-1
Copy link

mat-1 commented Jul 15, 2023

Note that this can be worked around by specifying a different resolver. The mongodb crate readme has an example.

@Firaenix
Copy link

I’m also running into this issue, I will do some investigating when I have some time

@mokeyish
Copy link
Contributor

Are you sure this can be reproduced? I don't seem to have encountered this problem, it has always been faster. You can download this program from here and see if it is too slow.

https://github.com/mokeyish/smartdns-rs#installing

@Firaenix
Copy link

Firaenix commented Sep 18, 2023

I can confirm that the slowdown is due to the amount and type of name_servers returned from the ipconfig crate, at least on my Windows machine. I would assume that depending on the machine it would differ but when trimming the following list down to a single DNS server from my Ethernet adapter, the lookup is in the milliseconds.

trust-dns-resolver is currently taking all adapters, including Virtual Machine adapters and Bluetooth and flat_map-ing the dns_servers in a naive way, if I removed all adapters that are not up, are not WiFi or Ethernet and are not Virtual adapters, it solved the performance issues for me.

I guess there is further discussion that needs to be had around if we do want to include Virtual adapters or bluetooth adapters.

What i've basically done in testing is add the following if statements to the flat_map

fn get_name_servers() -> ResolveResult<Vec<NameServerConfig>> {
    let adapters = get_adapters()?;
    let mut name_servers = vec![];

    for dns_server in adapters
        .iter()
        .flat_map(|adapter| {
            // If the adapter is not operating, ignore them
            if adapter.oper_status() != OperStatus::IfOperStatusUp {
                return [].iter();
            }

            // Only support Ethernet and WiFi devices
            if !(adapter.if_type() == IfType::Ieee80211 || adapter.if_type() == IfType::EthernetCsmacd) {
                return [].iter();
            }
           
            // Lazy removal of Virtual adapters or Hyper-V adapters
            if adapter.description().contains("Hyper-V") || adapter.description().contains("Virtual") {
                return [].iter();
            }

            adapter.dns_servers().iter()
        })
    {
        let socket_addr = SocketAddr::new(*dns_server, 53);
        name_servers.push(NameServerConfig {
            socket_addr,
            protocol: Protocol::Udp,
            tls_dns_name: None,
            trust_negative_responses: false,
            #[cfg(feature = "dns-over-rustls")]
            tls_config: None,
            bind_addr: None,
        });
        name_servers.push(NameServerConfig {
            socket_addr,
            protocol: Protocol::Tcp,
            tls_dns_name: None,
            trust_negative_responses: false,
            #[cfg(feature = "dns-over-rustls")]
            tls_config: None,
            bind_addr: None,
        });
    }
    Ok(name_servers)
}

Edit: More than happy to make a PR if this quick fix is good enough

Below is the list of adapters that were detected on my machine along with their DNS servers.
image

@bluejekyll
Copy link
Member

trust-dns-resolver is currently taking all adapters, including Virtual Machine adapters and Bluetooth and flat_map-ing the dns_servers in a naive way,

Yes, this sounds like exactly what others have noticed. I don't know what the "fix" is as I'm not using Windows and can't investigate. If you have a proposed change you'd like to put forward in a PR, I think we'd all be grateful.

@djc
Copy link
Collaborator

djc commented Sep 19, 2023

I'd suggest we should use something more like a deny list than an allow list here, to avoid unpleasant surprises? I think it makes sense to require IfOperStatusUp and deny Csmacd, not sure about the virtual stuff. I think Tailscale might like to be an adapter, for example...

@Firaenix
Copy link

I agree, I'm not sure if there is some generally accepted method of choosing which adapters to use in Windows-land.

In regard to Tailscale on Windows it comes up as an "Unsupported" type adapter and not a virtual adapter so it wasn't impacted by the virtual adapter exclusions but by the Ethernet and Wifi exclusions. Your point still stands though.

It is still surprisingly slow if you still have the WSL adapter in the adapter list though. I also believe that depending on the Windows install/users machine hardware and software installed there will be varying names for virtual adapters so it's hard to just disable them all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants