New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: IPv6 lookup fails when IPv4 hosts entry is present #20327

Open
luke-orden opened this Issue May 11, 2017 · 6 comments

Comments

Projects
None yet
5 participants
@luke-orden

luke-orden commented May 11, 2017

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.6 linux/amd64

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/luke/work"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GO15VENDOREXPERIMENT="1"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"

What did you do?

Add a IPv4 entry to the host file for example.com (do not add an IPv6 entry):

$ grep example.com /etc/hosts
1.2.3.4 example.com

Run the following code:

package main

import (
    "fmt"
    "net"
)

func main() {
    fmt.Println(net.ResolveIPAddr("ip6", "example.com"))
}

What did you expect to see?

When explicitly requesting an IPv6 address you should be returned an IPv6 if available via DNS even if there is an IPv4 address in the hosts file.

What did you see instead?

No addresses were returned:

$ GODEBUG=netdns=go go run dns.go 
<nil> no suitable address found
$ GODEBUG=netdns=cgo go run dns.go 
<nil> no suitable address found

This is because the request is passed from ipsock without specifying the desired address family:
https://github.com/golang/go/blob/master/src/net/ipsock.go#L259

Then dnsclient_unix performs a lookup against hosts, it finds an entry (IPv4 in this case) then returns this:
https://github.com/golang/go/blob/master/src/net/dnsclient_unix.go#L491-L494

ipsock then filters the returned addresses and only returns the IPs of the requested family:
https://github.com/golang/go/blob/master/src/net/ipsock.go#L265-L272

@bradfitz

This comment has been minimized.

Member

bradfitz commented May 11, 2017

@bradfitz

This comment has been minimized.

Member

bradfitz commented May 11, 2017

and @mdempsky

@pmarks-net

This comment has been minimized.

Contributor

pmarks-net commented May 11, 2017

I think this is working as intended. When you add a name to /etc/hosts, you're telling local resolvers to inhibit address lookups for the name. So if you define it as IPv4-only, then IPv4-only is what you get.

@luke-orden

This comment has been minimized.

luke-orden commented May 12, 2017

I understand your point, but I disagree. I think when an IPv4 host is added to a host file the system is being instructed to use that IP as a preferred IP. However if an IPv6 address is specifically requested and there isn't one present in the hosts file, but is via DNS, then it should be expected that the request will return the IPv6 address available via DNS.

This is how python acts:

$ grep example.com /etc/hosts
1.2.3.4 example.com
$
>>> socket.getaddrinfo("example.com", 80)
[(2, 1, 6, '', ('1.2.3.4', 80)), (2, 2, 17, '', ('1.2.3.4', 80)), (2, 3, 0, '', ('1.2.3.4', 80))]
>>> socket.getaddrinfo("example.com", 80, socket.AF_INET6)[0]
(10, 1, 6, '', ('2606:2800:220:1:248:1893:25c8:1946', 80, 0, 0))

It is also how ssh, ping6 etc work:

$ ssh -v example.com 2>&1 | grep Connecting
debug1: Connecting to example.com [1.2.3.4] port 22.

$ ssh -v -6 example.com 2>&1 | grep Connecting
debug1: Connecting to example.com [2606:2800:220:1:248:1893:25c8:1946] port 22.
$ ping6 example.com
PING example.com(2606:2800:220:1:248:1893:25c8:1946) 56 data bytes
@pmarks-net

This comment has been minimized.

Contributor

pmarks-net commented May 12, 2017

So, according to getaddrinfo, the name is IPv4-only if you ask for both, but still has IPv6 if you ask for IPv6?

That's pretty strange, but I can't argue with emulating whatever getaddrinfo does.

@mikioh

This comment has been minimized.

Contributor

mikioh commented Dec 1, 2017

I'm fine with relaxing the existing behavior of Lookup API by following some external configuration such as nsswitch.conf.

hosts: files dns // ask /etc/hosts then recursive servers
hosts: files // ask only /etc/hosts
hosts: dns // ask only recursive servers

Also fine to revisit the existing behavior. I can imagine it's pretty tough for people under some heterogenous environments to manage /etc/hosts, internal and public namespaces consistently.

@andybons andybons added this to the Unplanned milestone Apr 11, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment