-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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: prefer /etc/hosts over DNS when no /etc/nsswitch.conf is present #35305
Comments
When there is no /etc/nsswitch.conf file, the default for glibc for the If Go never looks at // If /etc/nsswitch.conf doesn't exist or doesn't specify any
// sources for "hosts", assume Go's DNS will work fine.
if os.IsNotExist(nss.err) || (nss.err == nil && len(srcs) == 0) {
if c.goos == "solaris" {
// illumos defaults to "nis [NOTFOUND=return] files"
return fallbackOrder
}
if c.goos == "linux" {
// glibc says the default is "dns [!UNAVAIL=return] files"
// https://www.gnu.org/software/libc/manual/html_node/Notes-on-NSS-Configuration-File.html.
return hostLookupDNSFiles
}
return hostLookupFilesDNS
} Changing Go to look at |
Thanks, @ianlancetaylor
I believe you indirectly pointed out the root problem: A potentially wrong assumption about the glibc default -- effectively based on an outdated glibc manual, as far as I can tell: The Go code in question points at some NSS glibc notes. BUT ... these notes were last updated in 1996 (!) by Ulrich Drepper:
Unsurprisingly, more than 20 years later, the NSS glibc notes seem outdated and seem to no longer match actual code. Comparing the commit from 1996 with current version, we have different behaviour nowadays:
Yes, there's still a mention of I've always been able to override DNS with local hosts entries in the past, without tweaking system defaults. I think it's a common, broadly documented use-case (example, showing that even Windows users can rely on
Given the current de-facto work-around for Alpine-based containers, including Go itself, is... RUN [ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf I'd kindly ask to reconsider my request, based on above observations: If someone has an account for glibc bugzilla, I'd appreciate if a bug could be opened there to further clarify/ensure that I'm not mistaken and this whole issue here just is simply based on their outdated docs ... and can safely be fixed in both places. Thanks! |
I filed an issue to clarify the apparent glibc documentation issue https://sourceware.org/bugzilla/show_bug.cgi?id=25156 If I'm not mistaken, glibc actually falls back to Will report back here for sure once the glibc issue brings clarification. |
I had to take another look at glibc code, with the friendly help of djdelorie on glibc IRC. He pointed me at Meaning: I was wrong, glibc really queries dns first in absence of But... It all still feels wrong?! I'll try to start that discussion over on libc-alpha now, as I was told the default change is at least discussable. Would you mind keeping this bug open some more days until I have feedback? Thanks! |
Retitled for clarity. We'll wait for @schnoddelbotz to report back about glibc, but even in the absence of progress there, it seems plausible to diverge from glibc and prefer /etc/hosts over DNS. Probably glibc never runs on systems where /etc/nsswitch.conf is missing, whereas Go clearly does. |
Thanks for proposing this fix @schnoddelbotz! What glibc and go are doing here feels very wrong, every sane /etc/nsswitch.conf configuration prefers files then dns. This is particularly a problem for networks that setup a search path as localhost can resolve to something completely wrong. For Alpine/musl systems this has been particularly painful, please fix asap! :) |
Thanks for retitling and reconsidering the issue as proposal, despite my previous misconception about glibc behaviour. There was only one response to the corresponding glibc-alpha thread in the last 6 days, but it was positive. Citing Florian Weimer's response:
I'd happily create a PR here now, but somehow doubt it's really helpful/needed? Just let me know... |
I think a PR is absolutely needed, https://golang.org/src/net/conf.go feels like a hot mess, it is making too many assumptions about the system. An upstream glibc change will have no effect on the go dns resolver, so go needs to change since it is making assumptions and emulating broken configs. I feel like this is an opportunity for Golang to be opinionated and consistent about what is happening here. For musl I would still need to set the |
I admittedly only focused on fixing the hosts-over-dns issue for Alpine with It's perfectly possible that I also mis-read Go code here (besides glibc), but are you sure that the tweak above wouldn't be sufficient |
Yah, maybe the magic behavior of when to use cgo dns should be a separate issue. I doubt very few people, if anyone, will want DNS then file resolution. The problem with the current net conf logic is the assumption that certain libraries are used, even tho that may not be the case. It is trying to be too magical and failing badly. Might as well just always return |
The consensus here seems overwhelming, and maybe glibc will even make the change. Leaving open for a week for final comments. |
No change in consensus. Accepted. |
Did not mean to close; sorry. |
Just ran into this issue myself in a really bizarre fashion so I wanted to notate it here just in case it was related. When debugging connectivity issues with Consul, I noticed that it would sometimes get the IP defined in the Example Consul outupt
In this case, the
The container is using host networking and pulls the |
We didn't cover much progress before the Go1.15 code freeze, thus I shall move this to the Go1.16 milestone. |
Do not mimic glibc behavior if /etc/nsswitch.conf is missing. This will will likely be missing on musl libc systems and glibc systems will likely always have it, resulting in localhost lookup being done over DNS rather than from /etc/hosts. Do what makes most sense rather than making any assumption about the libc. Fixes golang#35305
Do not mimic glibc behavior if /etc/nsswitch.conf is missing. This will will likely be missing on musl libc systems and glibc systems will likely always have it, resulting in localhost lookup being done over DNS rather than from /etc/hosts. Do what makes most sense rather than making any assumption about the libc. Fixes golang#35305
Change https://golang.org/cl/238629 mentions this issue: |
Do not mimic glibc behavior if /etc/nsswitch.conf is missing. This will will likely be missing on musl libc systems and glibc systems will likely always have it, resulting in localhost lookup being done over DNS rather than from /etc/hosts. Do what makes most sense rather than making any assumption about the libc. Fixes golang#35305
This is a workaround for golang/go#35305 which makes it possible to successfully push to a local registry using $ docker buildx build --push --tag localhost:5000/foo . assuming, of course, that the builder instance currently in use has been created using $ docker buildx create --driver-opt network=host The workaround is no longer going to be necessary once Go 1.16 is used for builds. Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Go <1.16 has unexpected default behavior when the /etc/nsswitch.conf file is missing: It will default to making a network request before looking in local files like /etc/hosts. Unfortunately the very popular alpine images do not have /etc/nsswitch.conf by default and so we must create one ourselves. There are many reports of this causing issues with name resolution: golang/go#22846 golang/go#35305 Until this is fixed in a released version of Go (hopefully 1.16) we need this change to ensure lookups happen in the expected way (files and then network). Change-Id: I246a767ae2767f0f83bf3b4229938a292cf9737e
see: golang/go#35305 (upstream operator-registry commit: 597b6ba90b2b13e3e0d1b90167fb1b6452505817)
see: golang/go#35305 Upstream-repository: operator-registry Upstream-commit: 597b6ba90b2b13e3e0d1b90167fb1b6452505817
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes, it does.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
CGO_ENABLED=0
--network=host
to let container connect to tunnellocalhost
as target to connect to:What did you expect to see?
The Go app should consider the container's
/etc/hosts
file to resolvelocalhost
to127.0.0.1
.What did you see instead?
The Go app did not consider
/etc/hosts
inside the container; it queried DNS servers to resolvelocalhost
. Actually, no/etc/hosts
entry would ever be considered, all lookups are using DNS directly.Some background / Summary
/etc/nsswitch.conf
.But Go, with
CGO_ENABLED=0
, does only consider/etc/hosts
if it finds a/etc/nsswitch.conf
. Alpine understandably rejects adding a/etc/nsswitch.conf
to work aroundquestionable Go behaviour (e.g. macOS also has no
/etc/nsswitch.conf
).In essence, everybody following documented Docker best-practices of using multi-stage builds and disabling CGO is prone to run into this issue sooner or later. In full paranoia mode, it could even be seen as security issue, as resolving
localhost
via DNS could be a potential attack vector, e.g. on public hot spots?By re-opening the issue, I'd kindly ask for review of the original issue and to reconsider whether Go's net package could be adjusted to use
/etc/hosts
if present, even if no/etc/nsswitch.conf
is found.The issue just consumes too much developer resources and introduces work-arounds in way too many places, IMHO. Finally, and just for laughs, we ran into this issue as some joker created a
localhost
entry in our LAN, pointing to his PC.The text was updated successfully, but these errors were encountered: