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

Open
jfbus opened this Issue Jan 9, 2019 · 2 comments

Comments

Projects
None yet
3 participants
@jfbus
Copy link

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 gopherbot added this to the Proposal milestone Jan 9, 2019

@gopherbot gopherbot added the Proposal label Jan 9, 2019

@gopherbot

This comment has been minimized.

Copy link

gopherbot commented Jan 10, 2019

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

@rsc

This comment has been minimized.

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

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