Skip to content

Commit 74ac37e

Browse files
ianlancetaylorgopherbot
authored andcommitted
[release-branch.go1.21] net: add GODEBUG=netedns0=0 to disable sending EDNS0 header
It reportedly breaks the DNS server on some modems. For #6464 For #21160 For #44135 For #51127 For #51153 For #67925 Fixes #67933 Change-Id: I54a11906159f00246d08a54cc8be7327e9ebfd2c Reviewed-on: https://go-review.googlesource.com/c/go/+/591995 LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Reviewed-by: Damien Neil <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> (cherry picked from commit ee4a42b) Reviewed-on: https://go-review.googlesource.com/c/go/+/592235 Commit-Queue: Ian Lance Taylor <[email protected]>
1 parent 7e563a0 commit 74ac37e

File tree

6 files changed

+65
-20
lines changed

6 files changed

+65
-20
lines changed

doc/godebug.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,13 @@ Go 1.19 made it an error for path lookups to resolve to binaries in the current
201201
controlled by the [`execerrdot` setting](/pkg/os/exec#hdr-Executables_in_the_current_directory).
202202
There is no plan to remove this setting.
203203

204+
Go 1.19 started sending EDNS0 additional headers on DNS requests.
205+
This can reportedly break the DNS server provided on some routers,
206+
such as CenturyLink Zyxel C3000Z.
207+
This can be changed by the [`netedns0` setting](/pkg/net#hdr-Name_Resolution).
208+
This setting is available in Go 1.21.12, Go 1.22.5, Go 1.23, and later.
209+
There is no plan to remove this setting.
210+
204211
### Go 1.18
205212

206213
Go 1.18 removed support for SHA1 in most X.509 certificates,

src/internal/godebugs/table.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ var All = []Info{
3939
{Name: "multipartmaxparts", Package: "mime/multipart"},
4040
{Name: "multipathtcp", Package: "net"},
4141
{Name: "netdns", Package: "net", Opaque: true},
42+
{Name: "netedns0", Package: "net", Changed: 19, Old: "0"},
4243
{Name: "panicnil", Package: "runtime", Changed: 21, Old: "1"},
4344
{Name: "randautoseed", Package: "math/rand"},
4445
{Name: "tarinsecurepath", Package: "archive/tar"},

src/net/dnsclient_unix.go

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package net
1717
import (
1818
"context"
1919
"errors"
20+
"internal/godebug"
2021
"internal/itoa"
2122
"io"
2223
"os"
@@ -52,6 +53,9 @@ var (
5253
errServerTemporarilyMisbehaving = errors.New("server misbehaving")
5354
)
5455

56+
// netedns0 controls whether we send an EDNS0 additional header.
57+
var netedns0 = godebug.New("netedns0")
58+
5559
func newRequest(q dnsmessage.Question, ad bool) (id uint16, udpReq, tcpReq []byte, err error) {
5660
id = uint16(randInt())
5761
b := dnsmessage.NewBuilder(make([]byte, 2, 514), dnsmessage.Header{ID: id, RecursionDesired: true, AuthenticData: ad})
@@ -62,16 +66,20 @@ func newRequest(q dnsmessage.Question, ad bool) (id uint16, udpReq, tcpReq []byt
6266
return 0, nil, nil, err
6367
}
6468

65-
// Accept packets up to maxDNSPacketSize. RFC 6891.
66-
if err := b.StartAdditionals(); err != nil {
67-
return 0, nil, nil, err
68-
}
69-
var rh dnsmessage.ResourceHeader
70-
if err := rh.SetEDNS0(maxDNSPacketSize, dnsmessage.RCodeSuccess, false); err != nil {
71-
return 0, nil, nil, err
72-
}
73-
if err := b.OPTResource(rh, dnsmessage.OPTResource{}); err != nil {
74-
return 0, nil, nil, err
69+
if netedns0.Value() == "0" {
70+
netedns0.IncNonDefault()
71+
} else {
72+
// Accept packets up to maxDNSPacketSize. RFC 6891.
73+
if err := b.StartAdditionals(); err != nil {
74+
return 0, nil, nil, err
75+
}
76+
var rh dnsmessage.ResourceHeader
77+
if err := rh.SetEDNS0(maxDNSPacketSize, dnsmessage.RCodeSuccess, false); err != nil {
78+
return 0, nil, nil, err
79+
}
80+
if err := b.OPTResource(rh, dnsmessage.OPTResource{}); err != nil {
81+
return 0, nil, nil, err
82+
}
7583
}
7684

7785
tcpReq, err = b.Finish()

src/net/dnsclient_unix_test.go

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2229,19 +2229,34 @@ func testGoLookupIPCNAMEOrderHostsAliases(t *testing.T, mode hostLookupOrder, lo
22292229
// This isn't a great test as it just tests the dnsmessage package
22302230
// against itself.
22312231
func TestDNSPacketSize(t *testing.T) {
2232+
t.Run("enabled", func(t *testing.T) {
2233+
testDNSPacketSize(t, false)
2234+
})
2235+
t.Run("disabled", func(t *testing.T) {
2236+
testDNSPacketSize(t, true)
2237+
})
2238+
}
2239+
2240+
func testDNSPacketSize(t *testing.T, disable bool) {
22322241
fake := fakeDNSServer{
22332242
rh: func(_, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
2234-
if len(q.Additionals) == 0 {
2235-
t.Error("missing EDNS record")
2236-
} else if opt, ok := q.Additionals[0].Body.(*dnsmessage.OPTResource); !ok {
2237-
t.Errorf("additional record type %T, expected OPTResource", q.Additionals[0])
2238-
} else if len(opt.Options) != 0 {
2239-
t.Errorf("found %d Options, expected none", len(opt.Options))
2243+
if disable {
2244+
if len(q.Additionals) > 0 {
2245+
t.Error("unexpected additional record")
2246+
}
22402247
} else {
2241-
got := int(q.Additionals[0].Header.Class)
2242-
t.Logf("EDNS packet size == %d", got)
2243-
if got != maxDNSPacketSize {
2244-
t.Errorf("EDNS packet size == %d, want %d", got, maxDNSPacketSize)
2248+
if len(q.Additionals) == 0 {
2249+
t.Error("missing EDNS record")
2250+
} else if opt, ok := q.Additionals[0].Body.(*dnsmessage.OPTResource); !ok {
2251+
t.Errorf("additional record type %T, expected OPTResource", q.Additionals[0])
2252+
} else if len(opt.Options) != 0 {
2253+
t.Errorf("found %d Options, expected none", len(opt.Options))
2254+
} else {
2255+
got := int(q.Additionals[0].Header.Class)
2256+
t.Logf("EDNS packet size == %d", got)
2257+
if got != maxDNSPacketSize {
2258+
t.Errorf("EDNS packet size == %d, want %d", got, maxDNSPacketSize)
2259+
}
22452260
}
22462261
}
22472262

@@ -2274,6 +2289,10 @@ func TestDNSPacketSize(t *testing.T) {
22742289
},
22752290
}
22762291

2292+
if disable {
2293+
t.Setenv("GODEBUG", "netedns0=0")
2294+
}
2295+
22772296
r := &Resolver{PreferGo: true, Dial: fake.DialContext}
22782297
if _, err := r.LookupIPAddr(context.Background(), "go.dev"); err != nil {
22792298
t.Errorf("lookup failed: %v", err)

src/net/net.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ to print debugging information about its decisions.
7171
To force a particular resolver while also printing debugging information,
7272
join the two settings by a plus sign, as in GODEBUG=netdns=go+1.
7373
74+
The Go resolver will send an EDNS0 additional header with a DNS request,
75+
to signal a willingness to accept a larger DNS packet size.
76+
This can reportedly cause sporadic failures with the DNS server run
77+
by some modems and routers. Setting GODEBUG=netedns0=0 will disable
78+
sending the additional header.
79+
7480
On macOS, if Go code that uses the net package is built with
7581
-buildmode=c-archive, linking the resulting archive into a C program
7682
requires passing -lresolv when linking the C code.

src/runtime/metrics/doc.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ Below is the full list of supported metrics, ordered lexicographically.
277277
The number of non-default behaviors executed by the net package
278278
due to a non-default GODEBUG=multipathtcp=... setting.
279279
280+
/godebug/non-default-behavior/netedns0:events
281+
The number of non-default behaviors executed by the net package
282+
due to a non-default GODEBUG=netedns0=... setting.
283+
280284
/godebug/non-default-behavior/panicnil:events
281285
The number of non-default behaviors executed by the runtime
282286
package due to a non-default GODEBUG=panicnil=... setting.

0 commit comments

Comments
 (0)