mirror of
https://github.com/golang/go.git
synced 2025-11-01 09:10:57 +00:00
net: support single-request resolv.conf option in pure Go resolver
There is a DNS resolution issue in Kubernetes (UDP response packets get dropped due to a race in conntrack between the parallel A and AAAA queries, causing timeouts in DNS queries).
A workaround is to enable single-request / single-request-reopen in resolv.conf in order to use sequential A and AAAA queries instead of parallel queries.
With this PR, the pure Go resolver searches for "single-request" and "single-request-reopen" in resolv.conf and send A and AAAA queries sequentially when found.
Fixes #29644
Change-Id: I906b3484008c1b9adf2e3e9241ea23767e29df59
GitHub-Last-Rev: d481acfb4c
GitHub-Pull-Request: golang/go#29661
Reviewed-on: https://go-review.googlesource.com/c/go/+/157377
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
33e5da48d5
commit
dbc1703781
6 changed files with 155 additions and 31 deletions
|
|
@ -17,6 +17,7 @@ import (
|
|||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -1621,3 +1622,76 @@ func TestTXTRecordTwoStrings(t *testing.T) {
|
|||
t.Errorf("txt[1], got %q, want %q", txt[1], want)
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 29644: support single-request resolv.conf option in pure Go resolver.
|
||||
// The A and AAAA queries will be sent sequentially, not in parallel.
|
||||
func TestSingleRequestLookup(t *testing.T) {
|
||||
defer dnsWaitGroup.Wait()
|
||||
var (
|
||||
firstcalled int32
|
||||
ipv4 int32 = 1
|
||||
ipv6 int32 = 2
|
||||
)
|
||||
fake := fakeDNSServer{rh: func(n, s string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
|
||||
r := dnsmessage.Message{
|
||||
Header: dnsmessage.Header{
|
||||
ID: q.ID,
|
||||
Response: true,
|
||||
},
|
||||
Questions: q.Questions,
|
||||
}
|
||||
for _, question := range q.Questions {
|
||||
switch question.Type {
|
||||
case dnsmessage.TypeA:
|
||||
if question.Name.String() == "slowipv4.example.net." {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
if !atomic.CompareAndSwapInt32(&firstcalled, 0, ipv4) {
|
||||
t.Errorf("the A query was received after the AAAA query !")
|
||||
}
|
||||
r.Answers = append(r.Answers, dnsmessage.Resource{
|
||||
Header: dnsmessage.ResourceHeader{
|
||||
Name: q.Questions[0].Name,
|
||||
Type: dnsmessage.TypeA,
|
||||
Class: dnsmessage.ClassINET,
|
||||
Length: 4,
|
||||
},
|
||||
Body: &dnsmessage.AResource{
|
||||
A: TestAddr,
|
||||
},
|
||||
})
|
||||
case dnsmessage.TypeAAAA:
|
||||
atomic.CompareAndSwapInt32(&firstcalled, 0, ipv6)
|
||||
r.Answers = append(r.Answers, dnsmessage.Resource{
|
||||
Header: dnsmessage.ResourceHeader{
|
||||
Name: q.Questions[0].Name,
|
||||
Type: dnsmessage.TypeAAAA,
|
||||
Class: dnsmessage.ClassINET,
|
||||
Length: 16,
|
||||
},
|
||||
Body: &dnsmessage.AAAAResource{
|
||||
AAAA: TestAddr6,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
return r, nil
|
||||
}}
|
||||
r := Resolver{PreferGo: true, Dial: fake.DialContext}
|
||||
|
||||
conf, err := newResolvConfTest()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer conf.teardown()
|
||||
if err := conf.writeAndUpdate([]string{"options single-request"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, name := range []string{"hostname.example.net", "slowipv4.example.net"} {
|
||||
firstcalled = 0
|
||||
_, err := r.LookupIPAddr(context.Background(), name)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue