4

In an earlier discussion on the topic of IPv6 Link-local addresses I saw a comment which stated:

Some would argue that using addresses instead of host names should be discouraged, for any type of addresses. Using mDNS to map to link-local addresses works fine.

The context of the discussion was that you need to specify an interface when using a link-local address.

I found the above comment surprising because I didn't expect mDNS to supply link information, thus I didn't expect it to "work fine". I constructed a simple test (below) to see if the information supplied by getaddrinfo included a link and I found the following:

  • Passing an address and link (eg: fe80::a:a:a:a%wlp3s0) to getaddrinfo resulted in a sockaddr_in6 with sin6_scope_id set to 3 (the index of my wlan card). This shows that getaddrinfo can supply link information.

  • Passing a hostname only resolvable by mDNS (which resolves to the same link-local address) resulted in a sockaddr_in6 with sin6_scope_id set to 0, i.e. no link was specified

  • Further I've confirmed that programs including SSH which rely on getaddrinfo to specify a link will fail when mDNS resolves a link-local address. But they will succeed if the IP address and link are specified explicitly.


Was the above comment wrong, or have I made a mistake in the way I test this? Can mDNS resolve to link-local address and specify the link?

For reference I'm testing on Debian Buster Linux version 4.19.0-5-amd647

My nsswitch.conf contains

hosts:          files mdns4_minimal [NOTFOUND=return] dns myhostname

Testcode.c:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>


int main(int arg_count, char ** args)
{
    struct addrinfo hints, *servinfo, *p;

    for (int i=1; i<arg_count; i++)
    {
        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_INET6; // to force IPv6
        hints.ai_socktype = SOCK_STREAM;
        printf("Checking %s\n", args[i]);
        if (getaddrinfo(args[i], "https", &hints, &servinfo)) {
            perror("getaddrinfo");
            continue;
        }

        for(p = servinfo; p != NULL; p = p->ai_next) {
            struct sockaddr_in6 * address = ((struct sockaddr_in6 *)p->ai_addr);
            printf("family %d scope %d\n", address->sin6_family, address->sin6_scope_id);
        }
        freeaddrinfo(servinfo);
    }

    return 0;
}
S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
Philip Couling
  • 13,581
  • 5
  • 53
  • 85
  • Sorry about trying to remove the Linux tag in an edit. Any smart person (when reading this fully) would've seen that it's most definitely about Linux. I've also proposed to add the [mdns] tag. Please review. – S.S. Anne May 29 '19 at 11:09
  • @JL2210 That's fine. It happens. – Philip Couling May 29 '19 at 11:19
  • This the same result I found when I tried it years ago, and I don't think it has really been developed since then :-). I have a vague feeling `systemd-resolved` + `nss-resolve` could do it. Note that it does not enable MDNS by default (why?), but it does enable LLMNR. I'm pretty confident *MDNS* can do it, but it depends on the implementation. – sourcejedi May 29 '19 at 17:01
  • @sourcejedi If you've got some steps to set that up and experiment I'd be interested to see them. I feel like LLMNR stands a bit more of a chance. One reason I'm dubious about mDNS is that I can't see anything stating that it only resolves names for that link. Since the DNS structure doesn't have space for link information, allowing names from outside the link to be resolved would prohibit the client from adding link information itself. – Philip Couling May 29 '19 at 17:08
  • @PhilipCouling heh. LLMNR equally adapts the DNS packet format. But both of them are link-local multicast protocols. It's very easy to know which link to use if you receive an LL address, it's the link you received the response packet on :-). And any implementation of a relay could reasonably drop LL address responses. You could try installing `libnss-resolve` on Ubuntu; the package install automatically edits nsswitch.conf. E.g. on a pair of VMs in virt-manager, which provides a virtual network but currently does not set up IPv6 by default, so you will only have link-local IPv6... – sourcejedi May 29 '19 at 17:28
  • That's just a suggestion though, I don't know the results either way. – sourcejedi May 29 '19 at 17:28
  • For LLMNR, you don't use `my-hostname-here.local`, you just use `my-hostname-here`. – sourcejedi May 29 '19 at 17:29
  • "_ One reason I'm dubious about mDNS is that I can't see anything stating that it only resolves names for that link._" Actually, mDNS uses the `224.0.0.251` multicast group, which is a Link-Local multicast group that cannot be sent to a different network, so, by definition, it on works on the link where it is used. – Ron Maupin Jul 15 '19 at 00:50
  • @RonMaupin You've fudged two concepts togeather. The protocol can only *communicate* on that link, yes. But does that automatically mean that it will only *resolve names to IPs on that same link*. If it does not only resolve names for IPs on that link, then how can an mDNS client infer which link a resolved name is for. The answer would be it can't. – Philip Couling Jul 15 '19 at 08:07
  • "_But does that automatically mean that it will only resolve names to IPs on that same link_" That is exactly what the RFC prescribes. There are checks for that. Also, it needs to maintain which on interface it was received: "_a host that wants to fully support this case needs network programming APIs that allow applications to specify on what interface to perform a link-local Multicast DNS query, and to discover on what interface a Multicast DNS response was received._" – Ron Maupin Jul 15 '19 at 08:33
  • Based on what you wrote, I assumed you had looked at the authoritative source: _[RFC 6762, Multicast DNS](https://tools.ietf.org/html/rfc6762)_. – Ron Maupin Jul 15 '19 at 08:36
  • It's in multiple sections, but in particular: "_A host sending Multicast DNS queries to a link-local destination address (including the 224.0.0.251 and FF02::FB link-local multicast addresses) MUST only accept responses to that query that originate from the local link, and silently discard any other response packets. Without this check, it could be possible for remote rogue hosts to send spoof answer packets (perhaps unicast to the victim host), which the receiving machine could misinterpret as having originated on the local link._" – Ron Maupin Jul 15 '19 at 08:42
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/196456/discussion-between-philip-couling-and-ron-maupin). – Philip Couling Jul 15 '19 at 08:48
  • Unfortunately, I need to go to bed right now. – Ron Maupin Jul 15 '19 at 08:49

0 Answers0