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)
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)