Bug #17112
closedResolv.getaddress fails with IPv6 link-local addresses
Description
I noticed that I cannot resolve any link-local IPv6 address using Resolv.getaddress
. For example calling Resolv.getaddress('fe80::eca4:7b00:ecc5:206c%8')
fails with Resolv::ResolvError
Resolving any IPv4 address succeedes, as well as resolving the loopback address ::1
.
After some code digging I noticed that Resolv::DNS
doesn't even attempt to resolve that IP address. It checks if there is any local IPv6 interface with an IP address which is not a loopback or a link-local address.
def each_address(name)
each_resource(name, Resource::IN::A) {|resource| yield resource.address}
if use_ipv6? # <===== false on my system
each_resource(name, Resource::IN::AAAA) {|resource| yield resource.address}
end
end
use_ipv6?
ultimately boils down to this:
Socket.ip_address_list.any? {|a| a.ipv6? && !a.ipv6_loopback? && !a.ipv6_linklocal? }
In other words if the system doesn't have a "real" IPv6 address, Resolv.getaddress
cannot resolve link-local addresses. (::1
is resolved using Resolv::Hosts
which doesn't perform the same check)
One could argue that IP addresses don't have to be resolved, and I could just perform a regex check and skip Resolv.getaddress
if I already have an IP address.
Unfortunately that is not possible when using resolv-replace
. In that case most (all?) of Ruby's address resolving is piped through Resolv.getaddress
.
(That is how I noticed this bug: The RubyMine test runner uses drb which connects to a process on the same machine using a link-local IPv6 address. Since I'm using resolv-replace
and I don't have a network interface with a non-loopback non-local-link address I encountered this bug.)
Platform:
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x64-mingw32]
Microsoft Windows [Version 10.0.18363.959]