]> Cypherpunks repositories - gostls13.git/commitdiff
net: send EDNS(0) packet length in DNS query
authorIan Lance Taylor <iant@golang.org>
Tue, 15 Feb 2022 21:46:56 +0000 (13:46 -0800)
committerIan Lance Taylor <iant@golang.org>
Thu, 3 Mar 2022 00:37:10 +0000 (00:37 +0000)
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 <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/net/dnsclient_unix.go
src/net/dnsclient_unix_test.go

index 9a4a6ee68c89174919e7f6647f4b6536e12256e3..b989d12c58f3eb74d909d04a9ae3dd6dce8c175d 100644 (file)
@@ -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
index e46decab16c98a8828edf7d488d6d78102788b6a..e5f01dba2adf02f342447de1c2f171e2263bb019 100644 (file)
@@ -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)
+       }
+}