[GH-ISSUE #2762] timeout - while nslookup provides response #1057

Closed
opened 2026-03-16 01:28:09 +03:00 by kerem · 1 comment
Owner

Originally created by @efraimglobusM on GitHub (Feb 10, 2025).
Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/2762

I am experiencing timeouts when performing an SRV record lookup using trust-dns-resolver. The same query works fine when using nslookup, which returns a non-authoritative response from my internal DNS server. However, trust-dns-resolver times out.

Expected Behavior
When running the following nslookup command:

nslookup -type=SRV _ldap._tcp.domain2.test.local
I get a non-authoritative answer:

Server: dc1.domain1.test.local
Address: daf::200

Non-authoritative answer:
_ldap._tcp.domain2.test.local SRV service location:
priority = 0
weight = 100
port = 389
svr hostname = dc5.domain2.test.local
I expect trust-dns-resolver to return dc5.domain2.test.local as the SRV target.

Actual Behavior
When I run the following Rust code i get timeout
Does trust-dns-resolver reject non-authoritative responses by default?
Is there a way to force it to accept non-authoritative answers like nslookup does?
Are there any debugging options to inspect why the resolver hangs or times out?

use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
use trust_dns_resolver::{TokioAsyncResolver, error::ResolveError};
use trust_dns_resolver::proto::rr::RecordType;
use tokio;

#[tokio::main]
async fn main() {
    let domain = "_ldap._tcp.domain2.test.local";

    match lookup_srv(domain).await {
        Ok(records) => println!("SRV records: {:?}", records),
        Err(e) => eprintln!("Lookup failed: {}", e),
    }
}

async fn lookup_srv(domain: &str) -> Result<Vec<String>, ResolveError> {
    let mut opts = ResolverOpts::default();
    let resolver = TokioAsyncResolver::tokio_from_system_conf()
        .map_err(|_| ResolveError::from("Failed to load system DNS settings"))?;

    let response = resolver.lookup(domain, RecordType::SRV).await?;

    let hostnames: Vec<String> = response
        .iter()
        .filter_map(|r| {
            if let trust_dns_resolver::proto::rr::RData::SRV(srv) = r {
                Some(srv.target().to_utf8())
            } else {
                None
            }
        })
        .collect();

    if hostnames.is_empty() {
        Err(ResolveError::from("No SRV records found"))
    } else {
        Ok(hostnames)
    }
}
Originally created by @efraimglobusM on GitHub (Feb 10, 2025). Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/2762 I am experiencing timeouts when performing an SRV record lookup using trust-dns-resolver. The same query works fine when using nslookup, which returns a non-authoritative response from my internal DNS server. However, trust-dns-resolver times out. Expected Behavior When running the following nslookup command: nslookup -type=SRV _ldap._tcp.domain2.test.local I get a non-authoritative answer: Server: dc1.domain1.test.local Address: daf::200 Non-authoritative answer: _ldap._tcp.domain2.test.local SRV service location: priority = 0 weight = 100 port = 389 svr hostname = dc5.domain2.test.local I expect trust-dns-resolver to return dc5.domain2.test.local as the SRV target. Actual Behavior When I run the following Rust code i get timeout Does trust-dns-resolver reject non-authoritative responses by default? Is there a way to force it to accept non-authoritative answers like nslookup does? Are there any debugging options to inspect why the resolver hangs or times out? ``` use trust_dns_resolver::config::{ResolverConfig, ResolverOpts}; use trust_dns_resolver::{TokioAsyncResolver, error::ResolveError}; use trust_dns_resolver::proto::rr::RecordType; use tokio; #[tokio::main] async fn main() { let domain = "_ldap._tcp.domain2.test.local"; match lookup_srv(domain).await { Ok(records) => println!("SRV records: {:?}", records), Err(e) => eprintln!("Lookup failed: {}", e), } } async fn lookup_srv(domain: &str) -> Result<Vec<String>, ResolveError> { let mut opts = ResolverOpts::default(); let resolver = TokioAsyncResolver::tokio_from_system_conf() .map_err(|_| ResolveError::from("Failed to load system DNS settings"))?; let response = resolver.lookup(domain, RecordType::SRV).await?; let hostnames: Vec<String> = response .iter() .filter_map(|r| { if let trust_dns_resolver::proto::rr::RData::SRV(srv) = r { Some(srv.target().to_utf8()) } else { None } }) .collect(); if hostnames.is_empty() { Err(ResolveError::from("No SRV records found")) } else { Ok(hostnames) } } ```
kerem closed this issue 2026-03-16 01:28:14 +03:00
Author
Owner

@efraimglobusM commented on GitHub (Feb 10, 2025):

tokio_from_system_conf solved the issue

async fn test_dns() {
        let domain = "_ldap._tcp.domain2.test.local";

        match lookup_srv(domain).await {
            Ok(records) => {
                for record in records {
                    println!("Resolved Host FQDN: {}", record);
                }
            }
            Err(e) => eprintln!("Lookup failed: {}", e),
        }
    }

    async fn lookup_srv(domain: &str) -> Result<Vec<String>, Box<dyn std::error::Error>> {
        // Create a system-aware resolver
        let mut opts = ResolverOpts::default();
        // Avoid unnecessary root queries

        let resolver = TokioAsyncResolver::tokio_from_system_conf()
            .map_err(|_| "Failed to load system DNS settings")?;

        let response = resolver.lookup(domain, RecordType::SRV).await?;

        let hostnames: Vec<String> = response
            .iter()
            .filter_map(|r| {
                if let RData::SRV(srv) = r {
                    Some(srv.target().to_utf8()) // Extract FQDN
                } else {
                    None
                }
            })
            .collect();

        if hostnames.is_empty() {
            Err("No SRV records found".into())
        } else {
            Ok(hostnames)
        }
    }
<!-- gh-comment-id:2649087443 --> @efraimglobusM commented on GitHub (Feb 10, 2025): tokio_from_system_conf solved the issue ``` async fn test_dns() { let domain = "_ldap._tcp.domain2.test.local"; match lookup_srv(domain).await { Ok(records) => { for record in records { println!("Resolved Host FQDN: {}", record); } } Err(e) => eprintln!("Lookup failed: {}", e), } } async fn lookup_srv(domain: &str) -> Result<Vec<String>, Box<dyn std::error::Error>> { // Create a system-aware resolver let mut opts = ResolverOpts::default(); // Avoid unnecessary root queries let resolver = TokioAsyncResolver::tokio_from_system_conf() .map_err(|_| "Failed to load system DNS settings")?; let response = resolver.lookup(domain, RecordType::SRV).await?; let hostnames: Vec<String> = response .iter() .filter_map(|r| { if let RData::SRV(srv) = r { Some(srv.target().to_utf8()) // Extract FQDN } else { None } }) .collect(); if hostnames.is_empty() { Err("No SRV records found".into()) } else { Ok(hostnames) } } ```
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/hickory-dns#1057
No description provided.