Skip to content

Commit

Permalink
net: send EDNS(0) packet length in DNS query
Browse files Browse the repository at this point in the history
We used to only accept up to 512 bytes in a DNS packet, per RFC 1035.
Increase the size we accept to 1232 bytes, per https://dnsflagday.net/2020/,
and advertise that larger limit in a EDNS(0) OPT record.

Fixes #6464
Fixes #21160
Fixes #44135
Fixes #51127

Change-Id: I496a294e9a8015de4161cbc1825b0dc5b4e9f5d8
Reviewed-on: https://go-review.googlesource.com/c/go/+/385035
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
  • Loading branch information
ianlancetaylor committed Feb 12, 2022
1 parent badba35 commit f14ad78
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 2 deletions.
19 changes: 18 additions & 1 deletion src/net/dnsclient_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ const (
// to be used as a useTCP parameter to exchange
useTCPOnly = true
useUDPOrTCP = false

// Requested DNS packet size.
// Value taken from https://dnsflagday.net/2020/.
maxDNSPacketSize = 1232
)

var (
Expand All @@ -56,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
Expand All @@ -82,7 +99,7 @@ func dnsPacketRoundTrip(c Conn, id uint16, query dnsmessage.Question, b []byte)
return dnsmessage.Parser{}, dnsmessage.Header{}, err
}

b = make([]byte, 512) // see RFC 1035
b = make([]byte, maxDNSPacketSize)
for {
n, err := c.Read(b)
if err != nil {
Expand Down
57 changes: 56 additions & 1 deletion src/net/dnsclient_unix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -881,7 +881,7 @@ func (f *fakeDNSPacketConn) Close() error {
func TestIgnoreDNSForgeries(t *testing.T) {
c, s := Pipe()
go func() {
b := make([]byte, 512)
b := make([]byte, maxDNSPacketSize)
n, err := s.Read(b)
if err != nil {
t.Error(err)
Expand Down Expand Up @@ -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)
}
}

0 comments on commit f14ad78

Please sign in to comment.