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: Pure-Go DNS resolver does not properly Round-Robin DNS Names #13283
Comments
I have an instinct that the problem lies in here (where returned addresses are being sorted) but I'm having a little trouble processing the code to understand the exact effects: https://golang.org/src/net/addrselect.go |
I'd suspect you're getting bit by "Rule 9: Use longest matching prefix". Does your server happen to have a 23.21.x.x address itself? |
@mdempsky it does not - it is only aware of an RFC1918 address (10.x.x.x) |
That at least explains why it's favoring the 23.x.x.x addresses over the 58.x.x.x and 184.x.x.x addresses: 23 shares 3 leading 0 bits with 10, whereas 58 and 184 share only 2 and 1 leading 0 bits with 10, respectively. |
It looks like glibc doesn't strictly follow RFC 3484/6724 for IPv4 addresses:
See http://bazaar.launchpad.net/~vcs-imports/glibc/master/view/head:/sysdeps/posix/getaddrinfo.c#L1710 |
EDIT: I lost the race on this comment to @mdempsky - it was written before the comment about glibc :-)
One thing I see in the RFC is this:
In practice, the behavior of routing by "best prefix" in this context is problematic, as it causes a significant amount of traffic to be pointed at a small subset of nodes that otherwise have no meaningful routing value over the others. |
Ah @mdempsky I think I would agree with their interpretation that it doesn't make sense once you're outside of the subnet. |
It's unfortunate that UDPConn's don't have a way to discover their local IPNet, only their IP. It looks like to match glibc's behavior, we'll need to call InterfaceAddrs and find the enclosing IPNet that way. (Which is basically how glibc finds IPv4 prefix lengths anyway.) Alternatively, we just skip Rule 9 for IPv4 addresses. I would suspect in practice it doesn't matter. CC @bradfitz |
Actually, we can still apply it for RFC 1918 private networks (i.e., 10/8, 172.16/12, and 192.168/16) relatively easily. |
@bmhatfield Are you able to test whether https://go-review.googlesource.com/#/c/16995/ fixes the problem for you? (Unfortunately I have to head out for a bit, hence the incomplete CL.) |
Yes, I can give it a shot. |
I canary-deployed this to a single host, and I can confirm that it is now including the other 3 non- |
CL https://golang.org/cl/16995 mentions this issue. |
CL https://golang.org/cl/34914 mentions this issue. |
I was recently debugging an issue with an Amazon Elastic Load Balancer where our traffic was not being evenly balanced across ELB Availability Zones. AWS's ELB uses a number of DNS entries and low TTLs to balance "front-door" client traffic, expecting clients to properly round-robin the addresses. This technique works for a large number of clients on the internet.
Unfortunately, the new pure-Go DNS resolver in 1.5 appears to have some affinity to lower-numbered addresses when returning addresses in round-robin form. The cgo resolver does not exhibit this behavior.
After tracing through some of the code, I believe I have a good reproduction case for this problem. The ELB in question returns 6 IP addresses.
I have written a small program to demonstrate the affinity behavior:
An alternate form of this program highlights the issue:
However, switching the resolver to
cgo
(on Ubuntu 12.04) causes the resolution to properly round-robin:And again, the even resolution behavior is highlighted by an alternate form of this program:
I believe the pure-Go DNS resolver should be updated to round-robin across all returned addresses.
The text was updated successfully, but these errors were encountered: