2

On Windows, I have two network interfaces with indexes 1 and 2 (according to route print).

I want to ping a host reachable from interface 2 using an IPv6 link-local address, say, fe80::42. This works:

> ping fe80::42
Pinging fe80::42 with 32 bytes of data:
Reply from fe80::42: time<1ms

> ping fe80::42%2
Pinging fe80::42%2 with 32 bytes of data:
Reply from fe80::42%2: time<1ms

So far so good.

Now, let's say that this interface 2 is configured with DNS suffix bar and with a DNS server that has an entry for foo.bar that returns fe80::42. I would expect to see something like this:

> ping /6 foo.bar
Pinging foo.bar [fe80::42%2] with 32 bytes of data:
Reply from fe80::42%2: time<1ms

But instead, I was surprised to find that Windows appears to be resolving the wrong scope:

> ping /6 foo.bar
Pinging foo.bar [fe80::42%1] with 32 bytes of data:
Destination host unreachable.

Why? How can I fix this so that Windows resolves foo.bar to fe80::42%2, not fe80::42%1?

Additional information

Windows version is 10.0.15063.

I have verified using a network sniffer that the DNS packets for resolving foo.bar are sent to the correct DNS server through interface 2, just as configured.

The most specific IPv6 route shown in route print clearly states that packets going to fe80::42 should go through interface 2. Basically I have manually added a route that looks like this:

 If  Metric  Network Destination  Gateway
 2   4242    fe80::42/128         On-link

I can see absolutely no reason why Windows would choose interface 1 for anything related to foo.bar or fe80::42.

I have independently verified that the output of getaddrinfo() is the culprit by building and running the example program from MSDN (slightly modified):

Calling getaddrinfo with following parameters:
        nodename = foo.bar
        servname (or port) = 0

getaddrinfo returned success
getaddrinfo response 1
        Flags: 0x0
        Family: AF_INET6 (IPv6)
        IPv6 address fe80::42%1
        Scope information: Zone 1 Level 0
        Socket type: SOCK_STREAM (stream)
        Protocol: IPPROTO_TCP (TCP)
        Length of this sockaddr: 28
        Canonical name: (null)

(Note the %1 and Zone 1 in the output)

Etienne Dechamps
  • 2,164
  • 8
  • 24
  • 28

1 Answers1

4

You cannot use link-local addresses in DNS.

Usage of those addresses is dependent on which link the client is connected to, and clients might even be connected to multiple links at the same time (ethernet + wifi for example). Or the client might be on a completely different link than the server, and the address it gets from DNS will be completely meaningless.

DNS records do not contain the scope, because scopes are local to each client. The DNS server has no way to give a meaningful scope to the client, so the protocol doesn't even include scope in the response. It would be meaningless.

So in short: DNS is for global scope addresses (which includes ULA, if you want to use local addresses)

Sander Steffann
  • 7,572
  • 18
  • 29
  • Well, in my case I am using IPv6 inside a fully private VPN isolated from the outside world. (Though one could argue a private LAN would be the same situation.) I don't see how having link-local addresses in DNS would be "meaningless" - sure, they only make sense in the context of one local network, but that certainly doesn't make them "meaningless". They do have meaning in the context of the network where the DNS server is located. – Etienne Dechamps May 21 '17 at 14:23
  • What you want to do is not supported by the underlying protocols. If it accidentally works: have fun, but don't expect it to work... – Sander Steffann May 21 '17 at 15:27
  • ULA addresses are used as private network, https://en.wikipedia.org/wiki/Unique_local_address – Mike Sep 27 '20 at 05:51