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

Feature: resolution of mDNS host name (.local) #261

Open
DrYak opened this issue Feb 12, 2025 · 3 comments
Open

Feature: resolution of mDNS host name (.local) #261

DrYak opened this issue Feb 12, 2025 · 3 comments

Comments

@DrYak
Copy link

DrYak commented Feb 12, 2025

Would there be an easy way for lan-mouse to resolve mDNS (avahi, etc.) host names so machines can easily find each other on the network?

Request:

Currently, it seems that lan-mouse treats them as a regular host name, adds the DNS domain and performs a normal look-up:


[left]
# hostname1
hostname = "nereid.local"

leads to:

2025-02-12T10:37:31Z WARN  lan_mouse::service] could not resolve nereid.local: no record found for Query { name: Name("nereid.local.ethz.ch."), query_type: AAAA, query_class: IN }

Adding a dot at least avoids appending the domain, but still performs normal DNS look-up (which fails):


[left]
# hostname1
hostname = "nereid.local."

leads to:

2025-02-12T10:37:31Z WARN  lan_mouse::service] could not resolve nereid.local: no record found for Query { name: Name("nereid.local."), query_type: AAAA, query_class: IN }

Is there some rust resolver library which could easily abstract that? (e.g.: something like the GNU C Library which uses /etc/nsswitch.conf)

Context:

my university uses horribly arcane automatic naming, based on the abstract connection to the wired 802.1x router to name the machines (today that netbook is bsse-bs-dock-128-117.ethz.ch.). Finding each-other based on mDNS is much more convenient, but currently I need to copy-paste the output of avahi-resolve-host-name -n nereid.local into an ip = [ … ] option of the config.toml

@feschber
Copy link
Owner

I really don't know too much about mDNS but I guess there is this crate which seems fairly popular: https://crates.io/crates/mdns

I will have to read up on the whole mDNS / avahi stuff though before I do something dumb.

@DrYak
Copy link
Author

DrYak commented Feb 18, 2025

I would say you don't (necessarily⁺) need to handle the whole mDNS support inside lan-mouse yourself.
(i.e.: You don't need to advertise services on the local net and auto-discover other clients and servers -- which is part of the purposes covered by mDNS. See the automatic discovery of stuff like AirPlay, CUPS and AirPrint, DLNA media streaming, etc. E.g. the demo code on that crate tries to auto-discover all Chromcast devices currently on the local network)
Among other you don't need to run your own multicast server to advertise whatever.

What you just need is the "resolve names" part: just being able to find the IP address that corresponds to a .local domain.

I think this would better cover the needs:
https://crates.io/crates/mdns-resolver

This crate performs local DNS lookups in a similar fashion as avahi-resolve -n; in other words, it translates Bonjour-style hostnames (e.g. foo.local) to an IP address.

and specially this part:

Most resolvers (including simple-mdns) are intended to browse or query services by type rather than name. This crate is intended to reliably discover the IP for a given hostname in the same fashion that a desktop device with Avahi or another similar local resolver would resolve hosts under the virtual .local domain.

The demo binary is exactly what lan-mouse would need to do:
https://github.com/timothyb89/mdns-resolver/blob/master/src/bin/mdns-query.rs#L32

let resolver = MdnsResolver::new().await?;
  let query = match env::args().skip(1).next() {
    Some(query) => query,
    None => {
      error!("usage: {} hostname", env::args().next().unwrap_or("mdns-query".into()));
      process::exit(1);
    }
  };

  let res = match resolver.query_timeout(query, Duration::from_millis(1000)).await {
    Ok(result) => result,
    Err(e) => {
      error!("could not resolve query: {}", e);
      process::exit(1);
    }
  };

  let packet = res.to_packet()?;
  for answer in packet.answers {
    let addr = match answer.rdata {
      simple_dns::rdata::RData::A(rec) => IpAddr::V4(Ipv4Addr::from(rec.address)),
      simple_dns::rdata::RData::AAAA(rec) => IpAddr::V6(Ipv6Addr::from(rec.address)),
      _ => continue,
    };
    println!("{} = {}", answer.name, addr);
  }

I just don't know how good this is as a package. (I'm not fluent in Rust)


⁺ : well, you could go the whole she-bang and implement a full mDNS server, and do automatic service discovery, and allow instances of lan-mouse on the same network to autodiscover each other, and e.g. rely on the encryption key to trust each other and put on the correct border. (i.e.: you completely drop machine names and ip addresses out of the configuration, you just have entries using public key and it's up to the multicast system to find if somewhere on the network there's a machine with authorised matching keys). But that's probably way beyond the scope of lan-mouse 1.0.

@tv42
Copy link

tv42 commented Feb 27, 2025

.local worked just fine for me. Maybe your system is not configured to resolve .local correctly? Try host nereid.local, if that doesn't work well...

[2025-02-27T22:41:48Z INFO  lan_mouse::dns] resolving (0) `foo.local` ...
[2025-02-27T22:41:59Z INFO  lan_mouse::dns] foo.local: adding ip 10.0.0.4

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

No branches or pull requests

3 participants