Skip to content
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: support single-request resolv.conf option in pure Go resolver #29644

Closed
jfbus opened this issue Jan 9, 2019 · 2 comments
Closed

net: support single-request resolv.conf option in pure Go resolver #29644

jfbus opened this issue Jan 9, 2019 · 2 comments

Comments

@jfbus
Copy link
Contributor

jfbus commented Jan 9, 2019

Context

There is a DNS resolution issue in Kubernetes (UDP response packets get dropped by conntrack, causing timeouts in DNS queries): kubernetes/kubernetes#56903

The issue is apparently caused by a race in conntrack between concurrent A and AAAA queries: https://www.weave.works/blog/racy-conntrack-and-dns-lookup-timeouts

A work-around is to configure the linux resolver to use TCP (e.g. using the use-vc option in resolv.conf), as discussed in #29358.

Another workaround is to enable single-request / single-request-reopen in resolv.conf in order to use sequential A and AAAA queries instead of concurrent queries - http://man7.org/linux/man-pages/man5/resolv.conf.5.html

Proposal

When parsing resolv.conf, we look for single-request/single-request-reopen and when set, do sequential queries in goLookupIPCNAMEOrder.

Here is what could be a small-footprint change:

Current code with concurrency:

	qtypes := [...]dnsmessage.Type{dnsmessage.TypeA, dnsmessage.TypeAAAA}
	for _, fqdn := range conf.nameList(name) {
		for _, qtype := range qtypes {
			dnsWaitGroup.Add(1)
			go func(qtype dnsmessage.Type) {
				p, server, err := r.tryOneName(ctx, conf, fqdn, qtype)
				lane <- racer{p, server, err}
				dnsWaitGroup.Done()
			}(qtype)
		}
		hitStrictError := false
		for range qtypes {
			racer := <-lane

replaced by:

	qtypes := [...]dnsmessage.Type{dnsmessage.TypeA, dnsmessage.TypeAAAA}
	var queryFn func(fqdn string, qtype dnsmessage.Type)
	var responseFn func(fqdn string, qtype dnsmessage.Type) racer
	if conf.singleRequest {
		queryFn = func(fqdn string, qtype dnsmessage.Type) {}
		responseFn = func(fqdn string, qtype dnsmessage.Type) racer {
			dnsWaitGroup.Add(1)
			defer dnsWaitGroup.Done()
			p, server, err := r.tryOneName(ctx, conf, fqdn, qtype)
			return racer{p, server, err}
		}
	} else {
		queryFn = func(fqdn string, qtype dnsmessage.Type) {
			dnsWaitGroup.Add(1)
			go func(qtype dnsmessage.Type) {
				p, server, err := r.tryOneName(ctx, conf, fqdn, qtype)
				lane <- racer{p, server, err}
				dnsWaitGroup.Done()
			}(qtype)
		}
		responseFn = func(fqdn string, qtype dnsmessage.Type) racer {
			return <- lane
		}
	}
	var lastErr error
	for _, fqdn := range conf.nameList(name) {
		for _, qtype := range qtypes {
			queryFn(fqdn, qtype)
		}
		hitStrictError := false
		for _, qtype := range qtypes {
			racer := responseFn(fqdn, qtype)
@gopherbot
Copy link

Change https://golang.org/cl/157377 mentions this issue: net: support single-request resolv.conf option in pure Go resolver

@rsc
Copy link
Contributor

rsc commented Jan 16, 2019

The rationale for accepting #29358 seems to apply here too. Checked with @bradfitz and others and they agree.

@rsc rsc modified the milestones: Proposal, Go1.13 Jan 16, 2019
@rsc rsc changed the title proposal: net: support single-request resolv.conf option in pure Go resolver net: support single-request resolv.conf option in pure Go resolver Jan 16, 2019
@golang golang locked and limited conversation to collaborators Apr 16, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants