-
Notifications
You must be signed in to change notification settings - Fork 18k
net: make LookupCNAME consistent between Unix and Windows, document #50101
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
Comments
I think LookupCNAME came about that way because we are using getaddrinfo, and it returns the underlying name almost as a side effect of the lookup, in res.ai_canonname. Should we stop using glibc for this call and make it match Windows? It might make it fail where it was succeeding before? Not sure. |
This proposal has been added to the active column of the proposals project |
The problem we have is that we need to use getaddrinfo(AI_CANONNAME) on Macs, because port 53 is blocked to non-libc code. Is there some way to make getaddrinfo succeed for hosts that have a CNAME record but for which that named host has no A/AAAA records? If not, it's very hard to implement the Windows LookupCNAME behavior on systems like Macs. |
Looks like even though it's not in the man pages, macOS may have res_ninit. So maybe we should look into using that in place of getaddrinfo(AI_CANONNAME). If that's possible, then it would seem OK to change this. The specific case being changed is when the name has a CNAME but no A/AAAA record, which is currently an error on Unix but succeeds on Windows. With this change, it would succeed everywhere in this (unusual) case. Does anyone want to look into how hard it would be to make the Go code use libresolv on Mac? That might also help for things like MX lookups. |
Sounds like we are still waiting for someone to check what can be done on the Mac. |
@bradfitz says there is a CL in net that got rolled back that used libresolv directly. The only problem was it used res_init instead of res_ninit, because the latter is undocumented (but apparently present). The relevant issue is #12524. Perhaps someone wants to try resurrecting that CL using the thread-safe APIs? Also related: #16345 and #31705. The rollback was https://go.dev/cl/180843. |
On hold for anyone who wants to try to implement the new behavior on Mac. |
Placed on hold. |
Hacked up something that seems to work on macOS. I will clean it up and mail it out next week. |
This proposal has been added to the active column of the proposals project |
I haven't cleaned it up yet, but it certainly seems to work and it passes Brad's test TXT record. Does anyone object to changing LookupCNAME to succeed for hosts with CNAME but not A records on Unix, like it already does on Windows? |
I've seen it used to get the local machine's FQDN, by passing the result of os.Hostname to LookupCNAME and letting the resolver worry about search domains and what not. That seems to be exactly the kind of thing that relies on LookupCNAME essentially behaving like gai's AI_CANONNAME. |
A quick search surfaces the package github.com/Showmax/go-fqdn which does just that. It falls back to other methods if LookupCNAME doesn't work but those rely on properly configured PTR records (or explicit /etc/hosts entries). If we changed LookupCNAME to be about CNAME records, I would prefer to have the "canonical name" behaviour available through some other way. |
Sorry, I don't understand. I had not realized AI_CANONNAME meant anything other than 'do a CNAME lookup'. What is the circumstance in which AI_CANONNAME consults something other than CNAME records, and what does it consult? |
Invoking getaddrinfo for the name "host" with AI_CANONNAME in ai_flags and an otherwise zero hints structure (meaning AF_UNSPEC) does the following (at least on glibc):
That's with "files dns" listed in nsswitch.conf. It's anyone's guess what it might do with other NSS modules. The Linux man pages describe this behaviour as:
I guess "official name" is meant to refer to the host's FQDN here. |
@slrz OK, it sounds like the difference is for hosts with A/AAAA records but no CNAME, such as 'google.com'. Normally we try very hard to avoid behavior changes, but in this case it is hard to see what would break given that Windows has never behaved the way Unix does, and we'd be making the Windows behavior the standard one. |
There are two possible options.
Given the rest of the API, with things like LookupMX, I think everyone expects LookupCNAME to mean (1) today. I certainly did. It seems like we should at least try to go down that path, and if we find out why we have to do (2), at least we'll know why. Maybe we could get the code for (1) ready to land at the start of the Go 1.20 cycle and see how far we get? Does anyone object to this? Or does anyone know why we must do (2)? |
Exactly, but more importantly also
Besides the "go-fqdn" library linked above, I know of at least one program that will be broken by this change in behaviour. As it's a companion program to the server parts of a video conferencing system that only run on Linux anyway (BigBlueButton), the current Windows behaviour is not very relevant. Usage there is like go-fqdn or the LookupCNAME("amsterdam") example above: invoke LookupCNAME with the result of os.Hostname as part of an attempt to mimic I'm not saying those are unfixable or that what they're doing is a good idea, just that they will break where they didn't before. |
Just returning the input string won't be sufficient: the callers are generally trying to mimic |
This definitely is something I don't want to break. Thanks. If we want to make LookupCNAME the same as much as possible on Linux and Windows without breaking existing uses, it looks like we could do a CNAME lookup (including adding DNS search suffixes), and if that works we're done, and otherwise fall back to A/AAAA lookup, and if that works, return the name that had the record. On Linux this would mean adding the explicit CNAME lookup, and on Windows it would mean adding the A/AAAA fallback. And then we could separately add a Does that sound reasonable? |
Based on the discussion above, this proposal seems like a likely accept. |
No change in consensus, so accepted. 🎉 |
Change https://go.dev/cl/446179 mentions this issue: |
Change https://go.dev/cl/451420 mentions this issue: |
For #50101 For #51152 For #53482 For #55301 For #56515 Change-Id: I11edeb4be0a7f80fb72fd7680a3407d081f83b8b Reviewed-on: https://go-review.googlesource.com/c/go/+/451420 TryBot-Result: Gopher Robot <gobot@golang.org> Auto-Submit: Damien Neil <dneil@google.com> Run-TryBot: Damien Neil <dneil@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com>
I looked at the implementation and it seems that when the DNS server responds with multiple CNAME like:
Then the LookupCNAME returns
Edit: on windows the last one in the chain is returned Line 409 in c0497d1
|
@rsc @ianlancetaylor
On unix systems we cannot only use the dns resolver. |
Change https://go.dev/cl/454397 mentions this issue: |
Change https://go.dev/cl/455275 mentions this issue: |
LookupCNAME is pretty weird right now.
Despite the name, it entirely ignores CNAME records on Unix. It launches
A
andAAAA
record lookups to recursive resolvers and returns the first response name found in theA
andAAAA
, skipping over anyCNAME
. (and not even asking for aCNAME
)But it documents that it does that...
https://pkg.go.dev/net#LookupCNAME
OTOH, on Windows, it does what you would expect from the name itself: it looks up CNAME records:
Here's a demo of a program behaving differently:
On Linux/Mac:
On Windows:
I like the Windows behavior better, FWIW. That's what I was looking for, but apparently it doesn't exist.
Can we either:
LookupCNAMERecord
that actually looks up a CNAME recordLookupCNAME
to be like Windows, perhaps adding aLookupCanonicalName
with the current weird Unix behavior ofLookupCNAME
?But at minimum: document whatever the rules are and make Unix and Windows match? At least in
Resolver.PreferGo
mode?The text was updated successfully, but these errors were encountered: