Control: retitle -1 libnss-mdns: DNS tried before mDNS despite configuration 
for mdns4_minimal first
Control: tags -1 + moreinfo

On Sat, 07 Feb 2026 at 10:54:21 +0900, 황병주 wrote:
mDNS name resolution via libnss-mdns is completely broken on Debian trixie
with glibc 2.41. The NSS module is loaded but never called, causing .local
hostnames to fall through to DNS instead of being resolved via mDNS.

I was unable to reproduce this on a trixie machine.

Steps:

1. Install libnss-mdns and avahi-daemon on Debian trixie (glibc 2.41)
. Have another host ($OTHER) with mDNS, on the same network
3. Edit /etc/nsswitch.conf to contain:
   hosts: files dns
4. getent hosts $OTHER.local; echo $? -> no output, exit status 2
5. Edit /etc/nsswitch.conf to contain:
   hosts: files mdns4_minimal [NOTFOUND=return] dns
6. getent hosts $OTHER.local; echo $? -> resolved, exit status 0

But, something that I *do* observe in this configuration is that a strace'd getent process does a connect() to my DNS server (in my case it's systemd-resolved) *before* connecting to the Avahi socket:

$ strace -e openat,connect getent hosts remnant.local
...
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_mdns4_minimal.so.2", 
O_RDONLY|O_CLOEXEC) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(53), 
sin_addr=inet_addr("127.0.0.53")}, 16) = 0
connect(3, {sa_family=AF_INET, sin_port=htons(53), 
sin_addr=inet_addr("127.0.0.53")}, 16) = 0
connect(3, {sa_family=AF_INET, sin_port=htons(53), 
sin_addr=inet_addr("127.0.0.53")}, 16) = 0
openat(AT_FDCWD, "/etc/hosts", O_RDONLY|O_CLOEXEC) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(53), 
sin_addr=inet_addr("127.0.0.53")}, 16) = 0
connect(3, {sa_family=AF_FILE, path="/run/avahi-daemon/socket"}, 110) = 0
REDACTED  remnant.local

I think that could result in the same symptom that you reported, where an ISP DNS server that (inappropriately) intercepts resolution of .local names results in the ISP's DNS resolution being used before mdns4_minimal gets an opportunity to step in.

I wonder whether this means that glibc is doing multiple lower-level NSS lookups for a single higher-level getent operation, only some of which are of a form implemented by mdns4_minimal, and as a result DNS effectively takes precedence over mDNS even though the configuration says the opposite?

LD_DEBUG reveals the root cause — glibc tries to resolve all NSS functions
and marks each missing one as fatal:

  $ LD_DEBUG=symbols getent hosts pluto.local 2>&1 | grep fatal | head -5
  symbol=_nss_mdns4_minimal_endaliasent; ... undefined symbol (fatal)
  symbol=_nss_mdns4_minimal_endetherent; ... undefined symbol (fatal)
  symbol=_nss_mdns4_minimal_endgrent; ... undefined symbol (fatal)
  symbol=_nss_mdns4_minimal_endhostent; ... undefined symbol (fatal)
  symbol=_nss_mdns4_minimal_endnetent; ... undefined symbol (fatal)

I think this is misleading: ld.so often says "fatal" when it doesn't really mean it. I think this should be read as "fatal to this particular attempt to resolve the symbol", and not as "fatal to any attempt to look up NSS".

    smcv

Reply via email to