diff options
author | Matthew Dempsky <mdempsky@google.com> | 2016-04-15 19:19:58 -0700 |
---|---|---|
committer | Matthew Dempsky <mdempsky@google.com> | 2016-04-22 22:16:08 +0000 |
commit | 3411d6321979b33291e3b4c6fe79d4dd41bd5fba (patch) | |
tree | 0382b4b7b3137e2c0c836279d2cec2dfc0fb812b /src/net/dnsclient_unix_test.go | |
parent | 9f1ccd647fcdb1b703c1042c90434e15aff75013 (diff) | |
download | go-3411d6321979b33291e3b4c6fe79d4dd41bd5fba.tar.gz go-3411d6321979b33291e3b4c6fe79d4dd41bd5fba.zip |
net: keep waiting for valid DNS response until timeout
Prevents denial of service attacks from bogus UDP packets.
Fixes #13281.
Change-Id: Ifb51b17a1b0807bfd27b144d6037431701184e7b
Reviewed-on: https://go-review.googlesource.com/22126
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/net/dnsclient_unix_test.go')
-rw-r--r-- | src/net/dnsclient_unix_test.go | 83 |
1 files changed, 70 insertions, 13 deletions
diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go index 761fb23f14..0b78adb853 100644 --- a/src/net/dnsclient_unix_test.go +++ b/src/net/dnsclient_unix_test.go @@ -567,9 +567,6 @@ func BenchmarkGoLookupIPWithBrokenNameServer(b *testing.B) { } type fakeDNSConn struct { - // last query - qmu sync.Mutex // guards q - q *dnsMsg // reply handler rh func(*dnsMsg) (*dnsMsg, error) } @@ -586,16 +583,76 @@ func (f *fakeDNSConn) SetDeadline(time.Time) error { return nil } -func (f *fakeDNSConn) writeDNSQuery(q *dnsMsg) error { - f.qmu.Lock() - defer f.qmu.Unlock() - f.q = q - return nil +func (f *fakeDNSConn) dnsRoundTrip(q *dnsMsg) (*dnsMsg, error) { + return f.rh(q) } -func (f *fakeDNSConn) readDNSResponse() (*dnsMsg, error) { - f.qmu.Lock() - q := f.q - f.qmu.Unlock() - return f.rh(q) +// UDP round-tripper algorithm should ignore invalid DNS responses (issue 13281). +func TestIgnoreDNSForgeries(t *testing.T) { + const TestAddr uint32 = 0x80420001 + + c, s := Pipe() + go func() { + b := make([]byte, 512) + n, err := s.Read(b) + if err != nil { + t.Fatal(err) + } + + msg := &dnsMsg{} + if !msg.Unpack(b[:n]) { + t.Fatal("invalid DNS query") + } + + s.Write([]byte("garbage DNS response packet")) + + msg.response = true + msg.id++ // make invalid ID + b, ok := msg.Pack() + if !ok { + t.Fatal("failed to pack DNS response") + } + s.Write(b) + + msg.id-- // restore original ID + msg.answer = []dnsRR{ + &dnsRR_A{ + Hdr: dnsRR_Header{ + Name: "www.example.com.", + Rrtype: dnsTypeA, + Class: dnsClassINET, + Rdlength: 4, + }, + A: TestAddr, + }, + } + + b, ok = msg.Pack() + if !ok { + t.Fatal("failed to pack DNS response") + } + s.Write(b) + }() + + msg := &dnsMsg{ + dnsMsgHdr: dnsMsgHdr{ + id: 42, + }, + question: []dnsQuestion{ + { + Name: "www.example.com.", + Qtype: dnsTypeA, + Qclass: dnsClassINET, + }, + }, + } + + resp, err := dnsRoundTripUDP(c, msg) + if err != nil { + t.Fatalf("dnsRoundTripUDP failed: %v", err) + } + + if got := resp.answer[0].(*dnsRR_A).A; got != TestAddr { + t.Error("got address %v, want %v", got, TestAddr) + } } |