Files
revsuit/internal/newdns/server_test.go
T
Li4n0 3559894acc feat: complete basic functions
Support http,dns and mysql connection. Support custom http, dns response. Support dns rebinding.
Support mysql load local files and jdbc deserialize exploit.
2021-04-21 18:55:16 +08:00

1828 lines
43 KiB
Go

package newdns
import (
"context"
"net"
"testing"
"time"
"github.com/miekg/dns"
"github.com/stretchr/testify/assert"
)
var awsNS = []string{
"ns-1071.awsdns-05.org.",
"ns-140.awsdns-17.com.",
"ns-1978.awsdns-55.co.uk.",
"ns-812.awsdns-37.net.",
}
const awsPrimaryNS = "ns-140.awsdns-17.com."
var awsOtherNS = []string{
"ns-1074.awsdns-06.org.",
"ns-1631.awsdns-11.co.uk.",
"ns-243.awsdns-30.com.",
"ns-869.awsdns-44.net.",
}
var nsRRs = []dns.RR{
&dns.NS{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 172800,
Rdlength: 23,
},
Ns: awsNS[0],
},
&dns.NS{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 172800,
Rdlength: 19,
},
Ns: awsNS[1],
},
&dns.NS{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 172800,
Rdlength: 25,
},
Ns: awsNS[2],
},
&dns.NS{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 172800,
Rdlength: 22,
},
Ns: awsNS[3],
},
}
var otherNSRRs = []dns.RR{
&dns.NS{
Hdr: dns.RR_Header{
Name: "other.newdns.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 23,
},
Ns: awsOtherNS[0],
},
&dns.NS{
Hdr: dns.RR_Header{
Name: "other.newdns.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 19,
},
Ns: awsOtherNS[1],
},
&dns.NS{
Hdr: dns.RR_Header{
Name: "other.newdns.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 25,
},
Ns: awsOtherNS[2],
},
&dns.NS{
Hdr: dns.RR_Header{
Name: "other.newdns.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 22,
},
Ns: awsOtherNS[3],
},
}
func TestAWS(t *testing.T) {
t.Run("UDP", func(t *testing.T) {
conformanceTests(t, "udp", awsPrimaryNS+":53", false)
})
t.Run("TCP", func(t *testing.T) {
conformanceTests(t, "tcp", awsPrimaryNS+":53", false)
})
t.Run("Resolver", func(t *testing.T) {
resolverTests(t, awsPrimaryNS+":53")
})
}
func TestServer(t *testing.T) {
zone := &Zone{
Name: "newdns.256dpi.com.",
MasterNameServer: awsPrimaryNS,
AllNameServers: []string{
awsNS[0],
awsNS[1],
awsNS[2],
awsNS[3],
},
AdminEmail: "[email protected]",
Refresh: 2 * time.Hour,
Retry: 15 * time.Minute,
Expire: 336 * time.Hour,
SOATTL: 15 * time.Minute,
NSTTL: 48 * time.Hour,
MinTTL: 5 * time.Minute,
Handler: func(name, remoteAddr string) ([]Set, error) {
// handle apex records
if name == "" {
return []Set{
{
Name: "newdns.256dpi.com.",
Type: A,
Records: []Record{
{Address: "1.2.3.4"},
},
},
{
Name: "newdns.256dpi.com.",
Type: AAAA,
Records: []Record{
{Address: "1:2:3:4::"},
},
},
{
Name: "newdns.256dpi.com.",
Type: TXT,
Records: []Record{
{Data: []string{"baz"}},
{Data: []string{"foo", "bar"}},
},
},
}, nil
}
// handle example
if name == "example" {
return []Set{
{
Name: "example.newdns.256dpi.com.",
Type: CNAME,
Records: []Record{
{Address: "example.com."},
},
},
}, nil
}
// handle ip4
if name == "ip4" {
return []Set{
{
Name: "ip4.newdns.256dpi.com.",
Type: A,
Records: []Record{
{Address: "1.2.3.4"},
},
},
}, nil
}
// handle ip6
if name == "ip6" {
return []Set{
{
Name: "ip6.newdns.256dpi.com.",
Type: AAAA,
Records: []Record{
{Address: "1:2:3:4::"},
},
},
}, nil
}
// handle mail
if name == "mail" {
return []Set{
{
Name: "mail.newdns.256dpi.com.",
Type: MX,
Records: []Record{
{Address: "mail.example.com.", Priority: 7},
},
},
}, nil
}
// handle multimail
if name == "multimail" {
return []Set{
{
Name: "multimail.newdns.256dpi.com.",
Type: MX,
Records: []Record{
{Address: "mail1.example.com.", Priority: 1},
{Address: "mail2.example.com.", Priority: 10},
{Address: "mail3.example.com.", Priority: 10},
},
},
}, nil
}
// handle text
if name == "text" {
return []Set{
{
Name: "text.newdns.256dpi.com.",
Type: TXT,
Records: []Record{
{Data: []string{"foo", "bar"}},
},
},
}, nil
}
// handle ref4
if name == "ref4" {
return []Set{
{
Name: "ref4.newdns.256dpi.com.",
Type: CNAME,
Records: []Record{
{Address: "ip4.newdns.256dpi.com."},
},
},
}, nil
}
// handle ref6
if name == "ref6" {
return []Set{
{
Name: "ref6.newdns.256dpi.com.",
Type: CNAME,
Records: []Record{
{Address: "ip6.newdns.256dpi.com."},
},
},
}, nil
}
// handle refref
if name == "refref" {
return []Set{
{
Name: "refref.newdns.256dpi.com.",
Type: CNAME,
Records: []Record{
{Address: "ref4.newdns.256dpi.com."},
},
},
}, nil
}
// handle ref4m
if name == "ref4m" {
return []Set{
{
Name: "ref4m.newdns.256dpi.com.",
Type: MX,
Records: []Record{
{Address: "ip4.newdns.256dpi.com.", Priority: 7},
},
},
}, nil
}
// handle ref6m
if name == "ref6m" {
return []Set{
{
Name: "ref6m.newdns.256dpi.com.",
Type: MX,
Records: []Record{
{Address: "ip6.newdns.256dpi.com.", Priority: 7},
},
},
}, nil
}
// handle long
if name == "long" {
return []Set{
{
Name: "long.newdns.256dpi.com.",
Type: TXT,
Records: []Record{
{Data: []string{"gyK4oL9X8Zn3b6TwmUIYAgQx43rBOWMqJWR3wGMGNaZgajnhd2u9JaIbGwNo6gzZunyKYRxID3mKLmYUCcIrNYuo8R4UkijZeshwqEAM2EWnjNsB1hJHOlu6VyRKW13rsFUJedOSqc7YjjUoxm9c3mF28tEXmc3GVsC476wJ2ciSbp7ujDjQ032SQRD6kpayzFX8GncS5KXP8mLK2ZIqK2U4fUmYEpTPQMmp7w24GKkfGJzE4JfMBxSybDUScLq"}},
{Data: []string{"upNh05zi9flqN2puI9eIGgAgl3gwc65l3WjFdnE3u55dhyUyIoKbOlc1mQJPULPkn1V5TTG9rLBB8AzNfeL8jvwO8h0mzmJhPH8n6dkgI546jB8Z0g0MRJxN5VNSixjFjdR8vtUp6EWlVi7QSe9SYInghV0M17zZ8mXSHwTfYZaPH54ng22mSWzVbRX2tlUPLTNRB5CHrEtxliyhhQlRey98P5G0eo35FUXdqzOSJ3HGqDssBWQAxK3I9feOjbE"}},
{Data: []string{"z4e6ycRMp6MP3WvWQMxIAOXglxANbj3oB0xD8BffktO4eo3VCR0s6TyGHKixvarOFJU0fqNkXeFOeI7sTXH5X0iXZukfLgnGTxLXNC7KkVFwtVFsh1P0IUNXtNBlOVWrVbxkS62ezbLpENNkiBwbkCvcTjwF2kyI0curAt9JhhJFb3AAq0q1iHWlJLn1KSrev9PIsY3alndDKjYTPxAojxzGKdK3A7rWLJ8Uzb3Z5OhLwP7jTKqbWVUocJRFLYp"}},
},
},
}, nil
}
// handle other
if name == "other" {
return []Set{
{
Name: "other.newdns.256dpi.com.",
Type: NS,
Records: []Record{
{Address: awsOtherNS[0]},
{Address: awsOtherNS[1]},
{Address: awsOtherNS[2]},
{Address: awsOtherNS[3]},
},
},
}, nil
}
return nil, nil
},
}
server := NewServer(Config{
BufferSize: 4096,
Handler: func(name string) (*Zone, error) {
if InZone("newdns.256dpi.com.", name) {
return zone, nil
}
return nil, nil
},
Logger: func(e Event, msg *dns.Msg, err error, reason string) {
if e == NetworkError {
panic(err.Error())
}
},
})
addr := "0.0.0.0:53001"
run(server, addr, func() {
t.Run("UDP", func(t *testing.T) {
conformanceTests(t, "udp", addr, true)
additionalTests(t, "udp", addr)
})
t.Run("TCP", func(t *testing.T) {
conformanceTests(t, "tcp", addr, true)
additionalTests(t, "tcp", addr)
})
t.Run("Resolver", func(t *testing.T) {
resolverTests(t, addr)
})
})
}
func TestServerFallback(t *testing.T) {
zone := &Zone{
Name: "example.com.",
MasterNameServer: "ns1.example.com.",
AllNameServers: []string{
"ns1.example.com.",
"ns2.example.com.",
},
Handler: func(name, remoteAddr string) ([]Set, error) {
// handle apex
if name == "" {
return []Set{
{
Name: "example.com.",
Type: A,
Records: []Record{
{Address: "1.2.3.4"},
},
},
}, nil
}
return nil, nil
},
}
server := NewServer(Config{
Zones: []string{"example.com."},
Handler: func(name string) (*Zone, error) {
if InZone("example.com.", name) {
return zone, nil
}
return nil, nil
},
Fallback: "1.1.1.1:53",
})
addr := "0.0.0.0:53002"
run(server, addr, func() {
// internal zone
ret, err := Query("udp", addr, "example.com.", "A", func(msg *dns.Msg) {
msg.RecursionDesired = true
})
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
RecursionDesired: true,
},
Question: []dns.Question{
{Name: "example.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.A{
Hdr: dns.RR_Header{
Name: "example.com.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 4,
},
A: net.ParseIP("1.2.3.4"),
},
},
Ns: []dns.RR{
&dns.NS{
Hdr: dns.RR_Header{
Name: "example.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 172800,
Rdlength: 6,
},
Ns: "ns1.example.com.",
},
&dns.NS{
Hdr: dns.RR_Header{
Name: "example.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 172800,
Rdlength: 6,
},
Ns: "ns2.example.com.",
},
},
}, ret)
// external zone
ret, err = Query("udp", addr, "newdns.256dpi.com.", "A", func(msg *dns.Msg) {
msg.RecursionDesired = true
})
assert.NoError(t, err)
ret.Answer[0].(*dns.A).Hdr.Ttl = 300
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: false,
RecursionDesired: true,
RecursionAvailable: true,
},
Question: []dns.Question{
{Name: "newdns.256dpi.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.A{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 4,
},
A: net.ParseIP("1.2.3.4"),
},
},
}, ret)
})
}
func conformanceTests(t *testing.T, proto, addr string, local bool) {
t.Run("ApexA", func(t *testing.T) {
ret, err := Query(proto, addr, "newdns.256dpi.com.", "A", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "newdns.256dpi.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.A{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 4,
},
A: net.ParseIP("1.2.3.4"),
},
},
Ns: nsRRs,
}, ret)
})
t.Run("ApexAAAA", func(t *testing.T) {
ret, err := Query(proto, addr, "newdns.256dpi.com.", "AAAA", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "newdns.256dpi.com.", Qtype: dns.TypeAAAA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.AAAA{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeAAAA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 16,
},
AAAA: net.ParseIP("1:2:3:4::"),
},
},
Ns: nsRRs,
}, ret)
})
t.Run("ApexCNAME", func(t *testing.T) {
ret, err := Query(proto, addr, "newdns.256dpi.com.", "CNAME", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
Rcode: dns.RcodeSuccess,
},
Question: []dns.Question{
{Name: "newdns.256dpi.com.", Qtype: dns.TypeCNAME, Qclass: dns.ClassINET},
},
Ns: []dns.RR{
&dns.SOA{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeSOA,
Class: dns.ClassINET,
Ttl: 900,
Rdlength: 66,
},
Ns: awsPrimaryNS,
Mbox: "awsdns-hostmaster.amazon.com.",
Serial: 1,
Refresh: 7200,
Retry: 900,
Expire: 1209600,
Minttl: 300,
},
},
}, ret)
})
t.Run("ApexSOA", func(t *testing.T) {
ret, err := Query(proto, addr, "newdns.256dpi.com.", "SOA", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "newdns.256dpi.com.", Qtype: dns.TypeSOA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.SOA{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeSOA,
Class: dns.ClassINET,
Ttl: 900,
Rdlength: 66,
},
Ns: awsPrimaryNS,
Mbox: "awsdns-hostmaster.amazon.com.",
Serial: 1,
Refresh: 7200,
Retry: 900,
Expire: 1209600,
Minttl: 300,
},
},
Ns: []dns.RR{
&dns.NS{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 172800,
Rdlength: 23,
},
Ns: awsNS[0],
},
&dns.NS{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 172800,
Rdlength: 2,
},
Ns: awsNS[1],
},
&dns.NS{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 172800,
Rdlength: 25,
},
Ns: awsNS[2],
},
&dns.NS{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 172800,
Rdlength: 22,
},
Ns: awsNS[3],
},
},
}, ret)
})
t.Run("ApexNS", func(t *testing.T) {
ret, err := Query(proto, addr, "newdns.256dpi.com.", "NS", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "newdns.256dpi.com.", Qtype: dns.TypeNS, Qclass: dns.ClassINET},
},
Answer: nsRRs,
}, ret)
})
t.Run("ApexTXT", func(t *testing.T) {
ret, err := Query(proto, addr, "newdns.256dpi.com.", "TXT", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "newdns.256dpi.com.", Qtype: dns.TypeTXT, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.TXT{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeTXT,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 4,
},
Txt: []string{"baz"},
},
&dns.TXT{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeTXT,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 8,
},
Txt: []string{"foo", "bar"},
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubA", func(t *testing.T) {
ret, err := Query(proto, addr, "ip4.newdns.256dpi.com.", "A", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "ip4.newdns.256dpi.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.A{
Hdr: dns.RR_Header{
Name: "ip4.newdns.256dpi.com.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 4,
},
A: net.ParseIP("1.2.3.4"),
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubAAAA", func(t *testing.T) {
ret, err := Query(proto, addr, "ip6.newdns.256dpi.com.", "AAAA", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "ip6.newdns.256dpi.com.", Qtype: dns.TypeAAAA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.AAAA{
Hdr: dns.RR_Header{
Name: "ip6.newdns.256dpi.com.",
Rrtype: dns.TypeAAAA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 16,
},
AAAA: net.ParseIP("1:2:3:4::"),
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubCNAME", func(t *testing.T) {
ret, err := Query(proto, addr, "example.newdns.256dpi.com.", "CNAME", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "example.newdns.256dpi.com.", Qtype: dns.TypeCNAME, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.CNAME{
Hdr: dns.RR_Header{
Name: "example.newdns.256dpi.com.",
Rrtype: dns.TypeCNAME,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 10,
},
Target: "example.com.",
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubMX", func(t *testing.T) {
ret, err := Query(proto, addr, "mail.newdns.256dpi.com.", "MX", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "mail.newdns.256dpi.com.", Qtype: dns.TypeMX, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.MX{
Hdr: dns.RR_Header{
Name: "mail.newdns.256dpi.com.",
Rrtype: dns.TypeMX,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 17,
},
Mx: "mail.example.com.",
Preference: 7,
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubMultiMX", func(t *testing.T) {
ret, err := Query(proto, addr, "multimail.newdns.256dpi.com.", "MX", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "multimail.newdns.256dpi.com.", Qtype: dns.TypeMX, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.MX{
Hdr: dns.RR_Header{
Name: "multimail.newdns.256dpi.com.",
Rrtype: dns.TypeMX,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 18,
},
Mx: "mail1.example.com.",
Preference: 1,
},
&dns.MX{
Hdr: dns.RR_Header{
Name: "multimail.newdns.256dpi.com.",
Rrtype: dns.TypeMX,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 10,
},
Mx: "mail2.example.com.",
Preference: 10,
},
&dns.MX{
Hdr: dns.RR_Header{
Name: "multimail.newdns.256dpi.com.",
Rrtype: dns.TypeMX,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 10,
},
Mx: "mail3.example.com.",
Preference: 10,
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubTXT", func(t *testing.T) {
ret, err := Query(proto, addr, "text.newdns.256dpi.com.", "TXT", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "text.newdns.256dpi.com.", Qtype: dns.TypeTXT, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.TXT{
Hdr: dns.RR_Header{
Name: "text.newdns.256dpi.com.",
Rrtype: dns.TypeTXT,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 8,
},
Txt: []string{"foo", "bar"},
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubCNAMEForA", func(t *testing.T) {
ret, err := Query(proto, addr, "example.newdns.256dpi.com.", "A", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "example.newdns.256dpi.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.CNAME{
Hdr: dns.RR_Header{
Name: "example.newdns.256dpi.com.",
Rrtype: dns.TypeCNAME,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 10,
},
Target: "example.com.",
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubCNAMEForAAAA", func(t *testing.T) {
ret, err := Query(proto, addr, "example.newdns.256dpi.com.", "AAAA", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "example.newdns.256dpi.com.", Qtype: dns.TypeAAAA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.CNAME{
Hdr: dns.RR_Header{
Name: "example.newdns.256dpi.com.",
Rrtype: dns.TypeCNAME,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 10,
},
Target: "example.com.",
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubCNAMEForAWithA", func(t *testing.T) {
ret, err := Query(proto, addr, "ref4.newdns.256dpi.com.", "A", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "ref4.newdns.256dpi.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.CNAME{
Hdr: dns.RR_Header{
Name: "ref4.newdns.256dpi.com.",
Rrtype: dns.TypeCNAME,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 6,
},
Target: "ip4.newdns.256dpi.com.",
},
&dns.A{
Hdr: dns.RR_Header{
Name: "ip4.newdns.256dpi.com.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 4,
},
A: net.ParseIP("1.2.3.4"),
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubCNAMEForAAAAWithAAAA", func(t *testing.T) {
ret, err := Query(proto, addr, "ref6.newdns.256dpi.com.", "AAAA", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "ref6.newdns.256dpi.com.", Qtype: dns.TypeAAAA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.CNAME{
Hdr: dns.RR_Header{
Name: "ref6.newdns.256dpi.com.",
Rrtype: dns.TypeCNAME,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 6,
},
Target: "ip6.newdns.256dpi.com.",
},
&dns.AAAA{
Hdr: dns.RR_Header{
Name: "ip6.newdns.256dpi.com.",
Rrtype: dns.TypeAAAA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 16,
},
AAAA: net.ParseIP("1:2:3:4::"),
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubCNAMEWithoutA", func(t *testing.T) {
ret, err := Query(proto, addr, "ref4.newdns.256dpi.com.", "CNAME", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "ref4.newdns.256dpi.com.", Qtype: dns.TypeCNAME, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.CNAME{
Hdr: dns.RR_Header{
Name: "ref4.newdns.256dpi.com.",
Rrtype: dns.TypeCNAME,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 6,
},
Target: "ip4.newdns.256dpi.com.",
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubCNAMEWithoutAAAA", func(t *testing.T) {
ret, err := Query(proto, addr, "ref6.newdns.256dpi.com.", "CNAME", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "ref6.newdns.256dpi.com.", Qtype: dns.TypeCNAME, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.CNAME{
Hdr: dns.RR_Header{
Name: "ref6.newdns.256dpi.com.",
Rrtype: dns.TypeCNAME,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 6,
},
Target: "ip6.newdns.256dpi.com.",
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubCNAMEForCNAMEForAWithA", func(t *testing.T) {
ret, err := Query(proto, addr, "refref.newdns.256dpi.com.", "A", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "refref.newdns.256dpi.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.CNAME{
Hdr: dns.RR_Header{
Name: "refref.newdns.256dpi.com.",
Rrtype: dns.TypeCNAME,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 7,
},
Target: "ref4.newdns.256dpi.com.",
},
&dns.CNAME{
Hdr: dns.RR_Header{
Name: "ref4.newdns.256dpi.com.",
Rrtype: dns.TypeCNAME,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 6,
},
Target: "ip4.newdns.256dpi.com.",
},
&dns.A{
Hdr: dns.RR_Header{
Name: "ip4.newdns.256dpi.com.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 4,
},
A: net.ParseIP("1.2.3.4"),
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubMXWithExtraA", func(t *testing.T) {
ret, err := Query(proto, addr, "ref4m.newdns.256dpi.com.", "MX", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "ref4m.newdns.256dpi.com.", Qtype: dns.TypeMX, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.MX{
Hdr: dns.RR_Header{
Name: "ref4m.newdns.256dpi.com.",
Rrtype: dns.TypeMX,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 8,
},
Preference: 7,
Mx: "ip4.newdns.256dpi.com.",
},
},
Extra: []dns.RR{
&dns.A{
Hdr: dns.RR_Header{
Name: "ip4.newdns.256dpi.com.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 4,
},
A: net.ParseIP("1.2.3.4"),
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubMXWithExtraAAAA", func(t *testing.T) {
ret, err := Query(proto, addr, "ref6m.newdns.256dpi.com.", "MX", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "ref6m.newdns.256dpi.com.", Qtype: dns.TypeMX, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.MX{
Hdr: dns.RR_Header{
Name: "ref6m.newdns.256dpi.com.",
Rrtype: dns.TypeMX,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 8,
},
Preference: 7,
Mx: "ip6.newdns.256dpi.com.",
},
},
Extra: []dns.RR{
&dns.AAAA{
Hdr: dns.RR_Header{
Name: "ip6.newdns.256dpi.com.",
Rrtype: dns.TypeAAAA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 16,
},
AAAA: net.ParseIP("1:2:3:4::"),
},
},
Ns: nsRRs,
}, ret)
})
t.Run("SubNS", func(t *testing.T) {
ret, err := Query(proto, addr, "other.newdns.256dpi.com.", "NS", nil)
assert.NoError(t, err)
order(ret.Ns)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: false,
},
Question: []dns.Question{
{Name: "other.newdns.256dpi.com.", Qtype: dns.TypeNS, Qclass: dns.ClassINET},
},
Ns: order(otherNSRRs),
}, ret)
})
t.Run("NoExactRecord", func(t *testing.T) {
assertMissing(t, proto, addr, "ip4.newdns.256dpi.com.", "CNAME", dns.RcodeSuccess)
assertMissing(t, proto, addr, "ip6.newdns.256dpi.com.", "CNAME", dns.RcodeSuccess)
assertMissing(t, proto, addr, "ip4.newdns.256dpi.com.", "AAAA", dns.RcodeSuccess)
assertMissing(t, proto, addr, "ip6.newdns.256dpi.com.", "A", dns.RcodeSuccess)
assertMissing(t, proto, addr, "mail.newdns.256dpi.com.", "A", dns.RcodeSuccess)
assertMissing(t, proto, addr, "text.newdns.256dpi.com.", "A", dns.RcodeSuccess)
assertMissing(t, proto, addr, "ip4.newdns.256dpi.com.", "NS", dns.RcodeSuccess)
})
t.Run("NoExistingRecord", func(t *testing.T) {
assertMissing(t, proto, addr, "missing.newdns.256dpi.com.", "A", dns.RcodeNameError)
assertMissing(t, proto, addr, "missing.newdns.256dpi.com.", "AAAA", dns.RcodeNameError)
assertMissing(t, proto, addr, "missing.newdns.256dpi.com.", "CNAME", dns.RcodeNameError)
assertMissing(t, proto, addr, "missing.newdns.256dpi.com.", "MX", dns.RcodeNameError)
assertMissing(t, proto, addr, "missing.newdns.256dpi.com.", "TXT", dns.RcodeNameError)
assertMissing(t, proto, addr, "missing.newdns.256dpi.com.", "NS", dns.RcodeNameError)
})
t.Run("TruncatedResponse", func(t *testing.T) {
ret, err := Query(proto, addr, "long.newdns.256dpi.com.", "TXT", nil)
assert.NoError(t, err)
if proto == "udp" {
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
Truncated: true,
},
Question: []dns.Question{
{Name: "long.newdns.256dpi.com.", Qtype: dns.TypeTXT, Qclass: dns.ClassINET},
},
}, ret)
} else {
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "long.newdns.256dpi.com.", Qtype: dns.TypeTXT, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.TXT{
Hdr: dns.RR_Header{
Name: "long.newdns.256dpi.com.",
Rrtype: dns.TypeTXT,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 256,
},
Txt: []string{
"gyK4oL9X8Zn3b6TwmUIYAgQx43rBOWMqJWR3wGMGNaZgajnhd2u9JaIbGwNo6gzZunyKYRxID3mKLmYUCcIrNYuo8R4UkijZeshwqEAM2EWnjNsB1hJHOlu6VyRKW13rsFUJedOSqc7YjjUoxm9c3mF28tEXmc3GVsC476wJ2ciSbp7ujDjQ032SQRD6kpayzFX8GncS5KXP8mLK2ZIqK2U4fUmYEpTPQMmp7w24GKkfGJzE4JfMBxSybDUScLq",
},
},
&dns.TXT{
Hdr: dns.RR_Header{
Name: "long.newdns.256dpi.com.",
Rrtype: dns.TypeTXT,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 256,
},
Txt: []string{
"upNh05zi9flqN2puI9eIGgAgl3gwc65l3WjFdnE3u55dhyUyIoKbOlc1mQJPULPkn1V5TTG9rLBB8AzNfeL8jvwO8h0mzmJhPH8n6dkgI546jB8Z0g0MRJxN5VNSixjFjdR8vtUp6EWlVi7QSe9SYInghV0M17zZ8mXSHwTfYZaPH54ng22mSWzVbRX2tlUPLTNRB5CHrEtxliyhhQlRey98P5G0eo35FUXdqzOSJ3HGqDssBWQAxK3I9feOjbE",
},
},
&dns.TXT{
Hdr: dns.RR_Header{
Name: "long.newdns.256dpi.com.",
Rrtype: dns.TypeTXT,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 256,
},
Txt: []string{
"z4e6ycRMp6MP3WvWQMxIAOXglxANbj3oB0xD8BffktO4eo3VCR0s6TyGHKixvarOFJU0fqNkXeFOeI7sTXH5X0iXZukfLgnGTxLXNC7KkVFwtVFsh1P0IUNXtNBlOVWrVbxkS62ezbLpENNkiBwbkCvcTjwF2kyI0curAt9JhhJFb3AAq0q1iHWlJLn1KSrev9PIsY3alndDKjYTPxAojxzGKdK3A7rWLJ8Uzb3Z5OhLwP7jTKqbWVUocJRFLYp",
},
},
},
Ns: nsRRs,
}, ret)
}
})
t.Run("CaseTransfer", func(t *testing.T) {
ret, err := Query(proto, addr, "Ip4.NeWDnS.256dpi.com.", "A", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "Ip4.NeWDnS.256dpi.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.A{
Hdr: dns.RR_Header{
Name: "Ip4.NeWDnS.256dpi.com.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 4,
},
A: net.ParseIP("1.2.3.4"),
},
},
Ns: []dns.RR{
&dns.NS{
Hdr: dns.RR_Header{
Name: "NeWDnS.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 172800,
Rdlength: 23,
},
Ns: awsNS[0],
},
&dns.NS{
Hdr: dns.RR_Header{
Name: "NeWDnS.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 172800,
Rdlength: 19,
},
Ns: awsNS[1],
},
&dns.NS{
Hdr: dns.RR_Header{
Name: "NeWDnS.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 172800,
Rdlength: 25,
},
Ns: awsNS[2],
},
&dns.NS{
Hdr: dns.RR_Header{
Name: "NeWDnS.256dpi.com.",
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 172800,
Rdlength: 22,
},
Ns: awsNS[3],
},
},
}, ret)
})
t.Run("DomainWithSpace", func(t *testing.T) {
assertMissing(t, proto, addr, "\\ ip4.newdns.256dpi.com.", "NULL", dns.RcodeNameError)
})
t.Run("EDNSSuccess", func(t *testing.T) {
ret, err := Query(proto, addr, "newdns.256dpi.com.", "A", func(msg *dns.Msg) {
msg.SetEdns0(1337, false)
})
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "newdns.256dpi.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.A{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 4,
},
A: net.ParseIP("1.2.3.4"),
},
},
Ns: nsRRs,
Extra: []dns.RR{
&dns.OPT{
Hdr: dns.RR_Header{
Name: ".",
Rrtype: dns.TypeOPT,
Class: 4096,
Ttl: 0,
Rdlength: 0,
},
},
},
}, ret)
})
t.Run("EDNSError", func(t *testing.T) {
ret, err := Query(proto, addr, "missing.newdns.256dpi.com.", "A", func(msg *dns.Msg) {
msg.SetEdns0(1337, false)
})
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
Rcode: dns.RcodeNameError,
},
Question: []dns.Question{
{Name: "missing.newdns.256dpi.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET},
},
Ns: []dns.RR{
&dns.SOA{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeSOA,
Class: dns.ClassINET,
Ttl: 900,
Rdlength: 66,
},
Ns: awsPrimaryNS,
Mbox: "awsdns-hostmaster.amazon.com.",
Serial: 1,
Refresh: 7200,
Retry: 900,
Expire: 1209600,
Minttl: 300,
},
},
Extra: []dns.RR{
&dns.OPT{
Hdr: dns.RR_Header{
Name: ".",
Rrtype: dns.TypeOPT,
Class: 4096,
Ttl: 0,
Rdlength: 0,
},
},
},
}, ret)
})
t.Run("EDNSBadVersion", func(t *testing.T) {
ret, err := Query(proto, addr, "newdns.256dpi.com.", "A", func(msg *dns.Msg) {
msg.SetEdns0(1337, false)
msg.Extra[0].(*dns.OPT).SetVersion(2)
})
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
Rcode: dns.RcodeBadVers,
},
Question: []dns.Question{
{Name: "newdns.256dpi.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET},
},
Extra: []dns.RR{
&dns.OPT{
Hdr: dns.RR_Header{
Name: ".",
Rrtype: dns.TypeOPT,
Class: 4096,
Ttl: ret.Extra[0].Header().Ttl, // see below
Rdlength: 0,
},
},
},
}, ret)
// the AWS servers sometimes return a bit-flipped TTL value
ttl := ret.Extra[0].Header().Ttl
if !local {
assert.True(t, ttl == 0x1008000 || ttl == 0x1000000, ttl)
} else {
assert.Equal(t, uint32(dns.RcodeBadVers<<20), ttl)
}
})
t.Run("EDNSLongResponse", func(t *testing.T) {
ret, err := Query(proto, addr, "long.newdns.256dpi.com.", "TXT", func(msg *dns.Msg) {
msg.SetEdns0(1337, false)
})
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "long.newdns.256dpi.com.", Qtype: dns.TypeTXT, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.TXT{
Hdr: dns.RR_Header{
Name: "long.newdns.256dpi.com.",
Rrtype: dns.TypeTXT,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 256,
},
Txt: []string{
"gyK4oL9X8Zn3b6TwmUIYAgQx43rBOWMqJWR3wGMGNaZgajnhd2u9JaIbGwNo6gzZunyKYRxID3mKLmYUCcIrNYuo8R4UkijZeshwqEAM2EWnjNsB1hJHOlu6VyRKW13rsFUJedOSqc7YjjUoxm9c3mF28tEXmc3GVsC476wJ2ciSbp7ujDjQ032SQRD6kpayzFX8GncS5KXP8mLK2ZIqK2U4fUmYEpTPQMmp7w24GKkfGJzE4JfMBxSybDUScLq",
},
},
&dns.TXT{
Hdr: dns.RR_Header{
Name: "long.newdns.256dpi.com.",
Rrtype: dns.TypeTXT,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 256,
},
Txt: []string{
"upNh05zi9flqN2puI9eIGgAgl3gwc65l3WjFdnE3u55dhyUyIoKbOlc1mQJPULPkn1V5TTG9rLBB8AzNfeL8jvwO8h0mzmJhPH8n6dkgI546jB8Z0g0MRJxN5VNSixjFjdR8vtUp6EWlVi7QSe9SYInghV0M17zZ8mXSHwTfYZaPH54ng22mSWzVbRX2tlUPLTNRB5CHrEtxliyhhQlRey98P5G0eo35FUXdqzOSJ3HGqDssBWQAxK3I9feOjbE",
},
},
&dns.TXT{
Hdr: dns.RR_Header{
Name: "long.newdns.256dpi.com.",
Rrtype: dns.TypeTXT,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 256,
},
Txt: []string{
"z4e6ycRMp6MP3WvWQMxIAOXglxANbj3oB0xD8BffktO4eo3VCR0s6TyGHKixvarOFJU0fqNkXeFOeI7sTXH5X0iXZukfLgnGTxLXNC7KkVFwtVFsh1P0IUNXtNBlOVWrVbxkS62ezbLpENNkiBwbkCvcTjwF2kyI0curAt9JhhJFb3AAq0q1iHWlJLn1KSrev9PIsY3alndDKjYTPxAojxzGKdK3A7rWLJ8Uzb3Z5OhLwP7jTKqbWVUocJRFLYp",
},
},
},
Ns: nsRRs,
Extra: []dns.RR{
&dns.OPT{
Hdr: dns.RR_Header{
Name: ".",
Rrtype: dns.TypeOPT,
Class: 4096,
Ttl: 0,
Rdlength: 0,
},
},
},
}, ret)
})
t.Run("RecursionDesired", func(t *testing.T) {
ret, err := Query(proto, addr, "newdns.256dpi.com.", "A", func(msg *dns.Msg) {
msg.RecursionDesired = true
})
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
RecursionDesired: true,
},
Question: []dns.Question{
{Name: "newdns.256dpi.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.A{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 4,
},
A: net.ParseIP("1.2.3.4"),
},
},
Ns: nsRRs,
}, ret)
})
t.Run("UnsupportedMessage", func(t *testing.T) {
_, err := Query(proto, addr, "newdns.256dpi.com.", "A", func(msg *dns.Msg) {
msg.Response = true
})
assert.True(t, isIOError(err), err)
})
t.Run("UnsupportedOpcode", func(t *testing.T) {
_, err := Query(proto, addr, "newdns.256dpi.com.", "A", func(msg *dns.Msg) {
msg.Opcode = dns.OpcodeNotify
})
assert.True(t, isIOError(err), err)
})
t.Run("UnsupportedClass", func(t *testing.T) {
_, err := Query(proto, addr, "newdns.256dpi.com.", "A", func(msg *dns.Msg) {
msg.Question[0].Qclass = dns.ClassANY
})
assert.True(t, isIOError(err), err)
})
t.Run("IgnorePayload", func(t *testing.T) {
ret, err := Query(proto, addr, "newdns.256dpi.com.", "A", func(msg *dns.Msg) {
msg.Answer = []dns.RR{
&dns.A{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 4,
},
A: net.ParseIP("1.2.3.4"),
},
&dns.AAAA{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeAAAA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 4,
},
AAAA: net.ParseIP("1:2:3:4::"),
},
}
msg.Ns = []dns.RR{
nsRRs[0],
}
msg.Extra = []dns.RR{
&dns.TXT{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeTXT,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 4,
},
Txt: []string{"baz"},
},
}
})
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
},
Question: []dns.Question{
{Name: "newdns.256dpi.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET},
},
Answer: []dns.RR{
&dns.A{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 300,
Rdlength: 4,
},
A: net.ParseIP("1.2.3.4"),
},
},
Ns: nsRRs,
}, ret)
})
t.Run("MultipleQuestions", func(t *testing.T) {
_, err := Query(proto, addr, "newdns.256dpi.com.", "A", func(msg *dns.Msg) {
msg.Question = append(msg.Question, dns.Question{
Name: "newdns.256dpi.com.",
Qtype: dns.TypeA,
Qclass: dns.ClassINET,
})
})
assert.True(t, isIOError(err), err)
})
t.Run("UnsupportedType", func(t *testing.T) {
assertMissing(t, proto, addr, "missing.newdns.256dpi.com.", "NULL", dns.RcodeNameError)
})
t.Run("NonAuthoritativeZone", func(t *testing.T) {
ret, err := Query(proto, addr, "foo.256dpi.com.", "A", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: false,
Rcode: dns.RcodeRefused,
},
Question: []dns.Question{
{Name: "foo.256dpi.com.", Qtype: dns.TypeA, Qclass: dns.ClassINET},
},
}, ret)
})
}
func additionalTests(t *testing.T, proto, addr string) {
t.Run("UnsupportedAny", func(t *testing.T) {
ret, err := Query(proto, addr, "newdns.256dpi.com.", "ANY", nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
Rcode: dns.RcodeNotImplemented,
},
Question: []dns.Question{
{Name: "newdns.256dpi.com.", Qtype: dns.TypeANY, Qclass: dns.ClassINET},
},
}, ret)
})
}
func assertMissing(t *testing.T, proto, addr, name, typ string, code int) {
qt := dns.StringToType[typ]
ret, err := Query(proto, addr, name, typ, nil)
assert.NoError(t, err)
equalJSON(t, &dns.Msg{
MsgHdr: dns.MsgHdr{
Response: true,
Authoritative: true,
Rcode: code,
},
Question: []dns.Question{
{Name: name, Qtype: qt, Qclass: dns.ClassINET},
},
Ns: []dns.RR{
&dns.SOA{
Hdr: dns.RR_Header{
Name: "newdns.256dpi.com.",
Rrtype: dns.TypeSOA,
Class: dns.ClassINET,
Ttl: 900,
Rdlength: 66,
},
Ns: awsPrimaryNS,
Mbox: "awsdns-hostmaster.amazon.com.",
Serial: 1,
Refresh: 7200,
Retry: 900,
Expire: 1209600,
Minttl: 300,
},
},
}, ret)
}
func resolverTests(t *testing.T, fallback string) {
var dialer net.Dialer
resolver := net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (conn net.Conn, err error) {
return dialer.DialContext(ctx, network, fallback)
},
}
ctx := context.Background()
t.Run("LookupHost", func(t *testing.T) {
addrs, err := resolver.LookupHost(ctx, "newdns.256dpi.com")
assert.NoError(t, err)
assert.Equal(t, []string{"1.2.3.4", "1:2:3:4::"}, addrs)
})
t.Run("LookupCNAME", func(t *testing.T) {
cname, err := resolver.LookupCNAME(ctx, "ref4.newdns.256dpi.com")
assert.NoError(t, err)
assert.Equal(t, "ip4.newdns.256dpi.com.", cname)
})
t.Run("LookupTXT", func(t *testing.T) {
txt, err := resolver.LookupTXT(ctx, "newdns.256dpi.com")
assert.NoError(t, err)
assert.Equal(t, []string{"baz", "foobar"}, txt)
})
t.Run("LookupMX", func(t *testing.T) {
mx, err := resolver.LookupMX(ctx, "ref4m.newdns.256dpi.com")
assert.NoError(t, err)
assert.Equal(t, []*net.MX{
{Host: "ip4.newdns.256dpi.com.", Pref: 7},
}, mx)
})
t.Run("LookupNS", func(t *testing.T) {
ns, err := resolver.LookupNS(ctx, "other.newdns.256dpi.com")
assert.Error(t, err) // zone is not served by server
assert.Nil(t, ns)
})
}