From: Ian Lance Taylor Date: Tue, 15 Feb 2022 21:46:56 +0000 (-0800) Subject: net: send EDNS(0) packet length in DNS query X-Git-Tag: go1.19beta1~1186 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=301fd8ac8b6cd93708ad536eb054e1b081982a9b;p=gostls13.git net: send EDNS(0) packet length in DNS query Advertise to DNS resolvers that we are willing and able to accept up to 1232 bytes in a DNS packet. The value 1232 was chosen based on https://dnsflagday.net/2020/. For #6464 For #21160 For #44135 For #51127 Fixes #51153 Change-Id: If9182d5210bfe047cf0a4d46163effc6812ab677 Reviewed-on: https://go-review.googlesource.com/c/go/+/386016 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Damien Neil TryBot-Result: Gopher Robot --- diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go index 9a4a6ee68c..b989d12c58 100644 --- a/src/net/dnsclient_unix.go +++ b/src/net/dnsclient_unix.go @@ -60,6 +60,19 @@ func newRequest(q dnsmessage.Question) (id uint16, udpReq, tcpReq []byte, err er if err := b.Question(q); err != nil { return 0, nil, nil, err } + + // Accept packets up to maxDNSPacketSize. RFC 6891. + if err := b.StartAdditionals(); err != nil { + return 0, nil, nil, err + } + var rh dnsmessage.ResourceHeader + if err := rh.SetEDNS0(maxDNSPacketSize, dnsmessage.RCodeSuccess, false); err != nil { + return 0, nil, nil, err + } + if err := b.OPTResource(rh, dnsmessage.OPTResource{}); err != nil { + return 0, nil, nil, err + } + tcpReq, err = b.Finish() udpReq = tcpReq[2:] l := len(tcpReq) - 2 diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go index e46decab16..e5f01dba2a 100644 --- a/src/net/dnsclient_unix_test.go +++ b/src/net/dnsclient_unix_test.go @@ -2161,3 +2161,58 @@ func TestRootNS(t *testing.T) { t.Errorf("records = [%v]; want [%v]", strings.Join(records, " "), want[0]) } } + +// Test that we advertise support for a larger DNS packet size. +// This isn't a great test as it just tests the dnsmessage package +// against itself. +func TestDNSPacketSize(t *testing.T) { + fake := fakeDNSServer{ + rh: func(_, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { + if len(q.Additionals) == 0 { + t.Error("missing EDNS record") + } else if opt, ok := q.Additionals[0].Body.(*dnsmessage.OPTResource); !ok { + t.Errorf("additional record type %T, expected OPTResource", q.Additionals[0]) + } else if len(opt.Options) != 0 { + t.Errorf("found %d Options, expected none", len(opt.Options)) + } else { + got := int(q.Additionals[0].Header.Class) + t.Logf("EDNS packet size == %d", got) + if got != maxDNSPacketSize { + t.Errorf("EDNS packet size == %d, want %d", got, maxDNSPacketSize) + } + } + + // Hand back a dummy answer to verify that + // LookupIPAddr completes. + r := dnsmessage.Message{ + Header: dnsmessage.Header{ + ID: q.Header.ID, + Response: true, + RCode: dnsmessage.RCodeSuccess, + }, + Questions: q.Questions, + } + if q.Questions[0].Type == dnsmessage.TypeA { + 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, + }, + }, + } + } + return r, nil + }, + } + + r := &Resolver{PreferGo: true, Dial: fake.DialContext} + if _, err := r.LookupIPAddr(context.Background(), "go.dev"); err != nil { + t.Errorf("lookup failed: %v", err) + } +}