Skip to content

Commit fe9b3c3

Browse files
ianlancetaylorgopherbot
authored andcommitted
[release-branch.go1.22] 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 #67934 Change-Id: I54a11906159f00246d08a54cc8be7327e9ebfd2c Reviewed-on: https://go-review.googlesource.com/c/go/+/591995 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Damien Neil <dneil@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> (cherry picked from commit ee4a42b) Reviewed-on: https://go-review.googlesource.com/c/go/+/592217 TryBot-Bypass: Ian Lance Taylor <iant@golang.org> Commit-Queue: Ian Lance Taylor <iant@google.com>
1 parent b515c52 commit fe9b3c3

File tree

6 files changed

+65
-20
lines changed

6 files changed

+65
-20
lines changed

doc/godebug.md

+7
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,13 @@ Go 1.19 made it an error for path lookups to resolve to binaries in the current
248248
controlled by the [`execerrdot` setting](/pkg/os/exec#hdr-Executables_in_the_current_directory).
249249
There is no plan to remove this setting.
250250

251+
Go 1.19 started sending EDNS0 additional headers on DNS requests.
252+
This can reportedly break the DNS server provided on some routers,
253+
such as CenturyLink Zyxel C3000Z.
254+
This can be changed by the [`netedns0` setting](/pkg/net#hdr-Name_Resolution).
255+
This setting is available in Go 1.21.12, Go 1.22.5, Go 1.23, and later.
256+
There is no plan to remove this setting.
257+
251258
### Go 1.18
252259

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

src/internal/godebugs/table.go

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ var All = []Info{
4242
{Name: "multipartmaxparts", Package: "mime/multipart"},
4343
{Name: "multipathtcp", Package: "net"},
4444
{Name: "netdns", Package: "net", Opaque: true},
45+
{Name: "netedns0", Package: "net", Changed: 19, Old: "0"},
4546
{Name: "panicnil", Package: "runtime", Changed: 21, Old: "1"},
4647
{Name: "randautoseed", Package: "math/rand"},
4748
{Name: "tarinsecurepath", Package: "archive/tar"},

src/net/dnsclient_unix.go

+18-10
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"context"
1717
"errors"
1818
"internal/bytealg"
19+
"internal/godebug"
1920
"internal/itoa"
2021
"io"
2122
"os"
@@ -51,6 +52,9 @@ var (
5152
errServerTemporarilyMisbehaving = errors.New("server misbehaving")
5253
)
5354

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

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

7684
tcpReq, err = b.Finish()

src/net/dnsclient_unix_test.go

+29-10
Original file line numberDiff line numberDiff line change
@@ -2259,19 +2259,34 @@ func testGoLookupIPCNAMEOrderHostsAliases(t *testing.T, mode hostLookupOrder, lo
22592259
// This isn't a great test as it just tests the dnsmessage package
22602260
// against itself.
22612261
func TestDNSPacketSize(t *testing.T) {
2262+
t.Run("enabled", func(t *testing.T) {
2263+
testDNSPacketSize(t, false)
2264+
})
2265+
t.Run("disabled", func(t *testing.T) {
2266+
testDNSPacketSize(t, true)
2267+
})
2268+
}
2269+
2270+
func testDNSPacketSize(t *testing.T, disable bool) {
22622271
fake := fakeDNSServer{
22632272
rh: func(_, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
2264-
if len(q.Additionals) == 0 {
2265-
t.Error("missing EDNS record")
2266-
} else if opt, ok := q.Additionals[0].Body.(*dnsmessage.OPTResource); !ok {
2267-
t.Errorf("additional record type %T, expected OPTResource", q.Additionals[0])
2268-
} else if len(opt.Options) != 0 {
2269-
t.Errorf("found %d Options, expected none", len(opt.Options))
2273+
if disable {
2274+
if len(q.Additionals) > 0 {
2275+
t.Error("unexpected additional record")
2276+
}
22702277
} else {
2271-
got := int(q.Additionals[0].Header.Class)
2272-
t.Logf("EDNS packet size == %d", got)
2273-
if got != maxDNSPacketSize {
2274-
t.Errorf("EDNS packet size == %d, want %d", got, maxDNSPacketSize)
2278+
if len(q.Additionals) == 0 {
2279+
t.Error("missing EDNS record")
2280+
} else if opt, ok := q.Additionals[0].Body.(*dnsmessage.OPTResource); !ok {
2281+
t.Errorf("additional record type %T, expected OPTResource", q.Additionals[0])
2282+
} else if len(opt.Options) != 0 {
2283+
t.Errorf("found %d Options, expected none", len(opt.Options))
2284+
} else {
2285+
got := int(q.Additionals[0].Header.Class)
2286+
t.Logf("EDNS packet size == %d", got)
2287+
if got != maxDNSPacketSize {
2288+
t.Errorf("EDNS packet size == %d, want %d", got, maxDNSPacketSize)
2289+
}
22752290
}
22762291
}
22772292

@@ -2304,6 +2319,10 @@ func TestDNSPacketSize(t *testing.T) {
23042319
},
23052320
}
23062321

2322+
if disable {
2323+
t.Setenv("GODEBUG", "netedns0=0")
2324+
}
2325+
23072326
r := &Resolver{PreferGo: true, Dial: fake.DialContext}
23082327
if _, err := r.LookupIPAddr(context.Background(), "go.dev"); err != nil {
23092328
t.Errorf("lookup failed: %v", err)

src/net/net.go

+6
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

+4
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,10 @@ Below is the full list of supported metrics, ordered lexicographically.
290290
The number of non-default behaviors executed by the net package
291291
due to a non-default GODEBUG=multipathtcp=... setting.
292292
293+
/godebug/non-default-behavior/netedns0:events
294+
The number of non-default behaviors executed by the net package
295+
due to a non-default GODEBUG=netedns0=... setting.
296+
293297
/godebug/non-default-behavior/panicnil:events
294298
The number of non-default behaviors executed by the runtime
295299
package due to a non-default GODEBUG=panicnil=... setting.

0 commit comments

Comments
 (0)