Skip to content

Commit f14ad78

Browse files
net: send EDNS(0) packet length in DNS query
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 <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]>
1 parent badba35 commit f14ad78

File tree

2 files changed

+74
-2
lines changed

2 files changed

+74
-2
lines changed

src/net/dnsclient_unix.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ const (
3030
// to be used as a useTCP parameter to exchange
3131
useTCPOnly = true
3232
useUDPOrTCP = false
33+
34+
// Requested DNS packet size.
35+
// Value taken from https://dnsflagday.net/2020/.
36+
maxDNSPacketSize = 1232
3337
)
3438

3539
var (
@@ -56,6 +60,19 @@ func newRequest(q dnsmessage.Question) (id uint16, udpReq, tcpReq []byte, err er
5660
if err := b.Question(q); err != nil {
5761
return 0, nil, nil, err
5862
}
63+
64+
// Accept packets up to maxDNSPacketSize. RFC 6891.
65+
if err := b.StartAdditionals(); err != nil {
66+
return 0, nil, nil, err
67+
}
68+
var rh dnsmessage.ResourceHeader
69+
if err := rh.SetEDNS0(maxDNSPacketSize, dnsmessage.RCodeSuccess, false); err != nil {
70+
return 0, nil, nil, err
71+
}
72+
if err := b.OPTResource(rh, dnsmessage.OPTResource{}); err != nil {
73+
return 0, nil, nil, err
74+
}
75+
5976
tcpReq, err = b.Finish()
6077
udpReq = tcpReq[2:]
6178
l := len(tcpReq) - 2
@@ -82,7 +99,7 @@ func dnsPacketRoundTrip(c Conn, id uint16, query dnsmessage.Question, b []byte)
8299
return dnsmessage.Parser{}, dnsmessage.Header{}, err
83100
}
84101

85-
b = make([]byte, 512) // see RFC 1035
102+
b = make([]byte, maxDNSPacketSize)
86103
for {
87104
n, err := c.Read(b)
88105
if err != nil {

src/net/dnsclient_unix_test.go

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,7 @@ func (f *fakeDNSPacketConn) Close() error {
881881
func TestIgnoreDNSForgeries(t *testing.T) {
882882
c, s := Pipe()
883883
go func() {
884-
b := make([]byte, 512)
884+
b := make([]byte, maxDNSPacketSize)
885885
n, err := s.Read(b)
886886
if err != nil {
887887
t.Error(err)
@@ -2161,3 +2161,58 @@ func TestRootNS(t *testing.T) {
21612161
t.Errorf("records = [%v]; want [%v]", strings.Join(records, " "), want[0])
21622162
}
21632163
}
2164+
2165+
// Test that we advertise support for a larger DNS packet size.
2166+
// This isn't a great test as it just tests the dnsmessage package
2167+
// against itself.
2168+
func TestDNSPacketSize(t *testing.T) {
2169+
fake := fakeDNSServer{
2170+
rh: func(_, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
2171+
if len(q.Additionals) == 0 {
2172+
t.Error("missing EDNS record")
2173+
} else if opt, ok := q.Additionals[0].Body.(*dnsmessage.OPTResource); !ok {
2174+
t.Errorf("additional record type %T, expected OPTResource", q.Additionals[0])
2175+
} else if len(opt.Options) != 0 {
2176+
t.Errorf("found %d Options, expected none", len(opt.Options))
2177+
} else {
2178+
got := int(q.Additionals[0].Header.Class)
2179+
t.Logf("EDNS packet size == %d", got)
2180+
if got != maxDNSPacketSize {
2181+
t.Errorf("EDNS packet size == %d, want %d", got, maxDNSPacketSize)
2182+
}
2183+
}
2184+
2185+
// Hand back a dummy answer to verify that
2186+
// LookupIPAddr completes.
2187+
r := dnsmessage.Message{
2188+
Header: dnsmessage.Header{
2189+
ID: q.Header.ID,
2190+
Response: true,
2191+
RCode: dnsmessage.RCodeSuccess,
2192+
},
2193+
Questions: q.Questions,
2194+
}
2195+
if q.Questions[0].Type == dnsmessage.TypeA {
2196+
r.Answers = []dnsmessage.Resource{
2197+
{
2198+
Header: dnsmessage.ResourceHeader{
2199+
Name: q.Questions[0].Name,
2200+
Type: dnsmessage.TypeA,
2201+
Class: dnsmessage.ClassINET,
2202+
Length: 4,
2203+
},
2204+
Body: &dnsmessage.AResource{
2205+
A: TestAddr,
2206+
},
2207+
},
2208+
}
2209+
}
2210+
return r, nil
2211+
},
2212+
}
2213+
2214+
r := &Resolver{PreferGo: true, Dial: fake.DialContext}
2215+
if _, err := r.LookupIPAddr(context.Background(), "go.dev"); err != nil {
2216+
t.Errorf("lookup failed: %v", err)
2217+
}
2218+
}

0 commit comments

Comments
 (0)