2019-03-11 16:56:48 +00:00
|
|
|
package dns01
|
2018-12-06 21:50:17 +00:00
|
|
|
|
|
|
|
import (
|
2024-02-11 13:37:09 +00:00
|
|
|
"errors"
|
2018-12-06 21:50:17 +00:00
|
|
|
"sort"
|
|
|
|
"testing"
|
|
|
|
|
2024-02-11 13:37:09 +00:00
|
|
|
"github.com/miekg/dns"
|
2018-12-06 21:50:17 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestLookupNameserversOK(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
fqdn string
|
|
|
|
nss []string
|
|
|
|
}{
|
|
|
|
{
|
2023-06-27 21:42:01 +00:00
|
|
|
fqdn: "en.wikipedia.org.",
|
|
|
|
nss: []string{"ns0.wikimedia.org.", "ns1.wikimedia.org.", "ns2.wikimedia.org."},
|
2018-12-06 21:50:17 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
fqdn: "www.google.com.",
|
|
|
|
nss: []string{"ns1.google.com.", "ns2.google.com.", "ns3.google.com.", "ns4.google.com."},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
fqdn: "physics.georgetown.edu.",
|
|
|
|
nss: []string{"ns4.georgetown.edu.", "ns5.georgetown.edu.", "ns6.georgetown.edu."},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range testCases {
|
|
|
|
test := test
|
|
|
|
t.Run(test.fqdn, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
nss, err := lookupNameservers(test.fqdn)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
sort.Strings(nss)
|
|
|
|
sort.Strings(test.nss)
|
|
|
|
|
|
|
|
assert.EqualValues(t, test.nss, nss)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestLookupNameserversErr(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
desc string
|
|
|
|
fqdn string
|
|
|
|
error string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "invalid tld",
|
|
|
|
fqdn: "_null.n0n0.",
|
2024-02-11 13:37:09 +00:00
|
|
|
error: "could not find zone",
|
2018-12-06 21:50:17 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range testCases {
|
|
|
|
test := test
|
|
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
_, err := lookupNameservers(test.fqdn)
|
|
|
|
require.Error(t, err)
|
|
|
|
assert.Contains(t, err.Error(), test.error)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-24 22:58:50 +00:00
|
|
|
var findXByFqdnTestCases = []struct {
|
|
|
|
desc string
|
|
|
|
fqdn string
|
|
|
|
zone string
|
|
|
|
primaryNs string
|
|
|
|
nameservers []string
|
|
|
|
expectedError string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "domain is a CNAME",
|
|
|
|
fqdn: "mail.google.com.",
|
|
|
|
zone: "google.com.",
|
|
|
|
primaryNs: "ns1.google.com.",
|
|
|
|
nameservers: recursiveNameservers,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "domain is a non-existent subdomain",
|
|
|
|
fqdn: "foo.google.com.",
|
|
|
|
zone: "google.com.",
|
|
|
|
primaryNs: "ns1.google.com.",
|
|
|
|
nameservers: recursiveNameservers,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "domain is a eTLD",
|
|
|
|
fqdn: "example.com.ac.",
|
|
|
|
zone: "ac.",
|
|
|
|
primaryNs: "a0.nic.ac.",
|
|
|
|
nameservers: recursiveNameservers,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "domain is a cross-zone CNAME",
|
|
|
|
fqdn: "cross-zone-example.assets.sh.",
|
|
|
|
zone: "assets.sh.",
|
|
|
|
primaryNs: "gina.ns.cloudflare.com.",
|
|
|
|
nameservers: recursiveNameservers,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "NXDOMAIN",
|
2021-11-22 20:08:38 +00:00
|
|
|
fqdn: "test.lego.zz.",
|
|
|
|
zone: "lego.zz.",
|
2022-11-10 01:23:04 +00:00
|
|
|
nameservers: []string{"8.8.8.8:53"},
|
2024-02-11 13:37:09 +00:00
|
|
|
expectedError: "[fqdn=test.lego.zz.] could not find the start of authority for 'test.lego.zz.' [question='zz. IN SOA', code=NXDOMAIN]",
|
2019-10-24 22:58:50 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "several non existent nameservers",
|
|
|
|
fqdn: "mail.google.com.",
|
|
|
|
zone: "google.com.",
|
|
|
|
primaryNs: "ns1.google.com.",
|
2022-11-10 01:23:04 +00:00
|
|
|
nameservers: []string{":7053", ":8053", "8.8.8.8:53"},
|
2019-10-24 22:58:50 +00:00
|
|
|
},
|
|
|
|
{
|
2024-02-11 13:37:09 +00:00
|
|
|
desc: "only non-existent nameservers",
|
|
|
|
fqdn: "mail.google.com.",
|
|
|
|
zone: "google.com.",
|
|
|
|
nameservers: []string{":7053", ":8053", ":9053"},
|
|
|
|
// use only the start of the message because the port changes with each call: 127.0.0.1:XXXXX->127.0.0.1:7053.
|
|
|
|
expectedError: "[fqdn=mail.google.com.] could not find the start of authority for 'mail.google.com.': DNS call error: read udp ",
|
2019-10-24 22:58:50 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "no nameservers",
|
|
|
|
fqdn: "test.ldez.com.",
|
|
|
|
zone: "ldez.com.",
|
|
|
|
nameservers: []string{},
|
2024-02-11 13:37:09 +00:00
|
|
|
expectedError: "[fqdn=test.ldez.com.] could not find the start of authority for 'test.ldez.com.': empty list of nameservers",
|
2019-10-24 22:58:50 +00:00
|
|
|
},
|
|
|
|
}
|
2018-12-06 21:50:17 +00:00
|
|
|
|
2019-10-24 22:58:50 +00:00
|
|
|
func TestFindZoneByFqdnCustom(t *testing.T) {
|
|
|
|
for _, test := range findXByFqdnTestCases {
|
2018-12-06 21:50:17 +00:00
|
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
|
|
ClearFqdnCache()
|
|
|
|
|
|
|
|
zone, err := FindZoneByFqdnCustom(test.fqdn, test.nameservers)
|
|
|
|
if test.expectedError != "" {
|
|
|
|
require.Error(t, err)
|
2024-02-11 13:37:09 +00:00
|
|
|
assert.ErrorContains(t, err, test.expectedError)
|
2018-12-06 21:50:17 +00:00
|
|
|
} else {
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, test.zone, zone)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-10 01:23:04 +00:00
|
|
|
func TestFindPrimaryNsByFqdnCustom(t *testing.T) {
|
2019-10-24 22:58:50 +00:00
|
|
|
for _, test := range findXByFqdnTestCases {
|
|
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
|
|
ClearFqdnCache()
|
|
|
|
|
|
|
|
ns, err := FindPrimaryNsByFqdnCustom(test.fqdn, test.nameservers)
|
|
|
|
if test.expectedError != "" {
|
|
|
|
require.Error(t, err)
|
2024-02-11 13:37:09 +00:00
|
|
|
assert.ErrorContains(t, err, test.expectedError)
|
2019-10-24 22:58:50 +00:00
|
|
|
} else {
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, test.primaryNs, ns)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-06 21:50:17 +00:00
|
|
|
func TestResolveConfServers(t *testing.T) {
|
2020-07-09 23:48:18 +00:00
|
|
|
testCases := []struct {
|
2018-12-06 21:50:17 +00:00
|
|
|
fixture string
|
|
|
|
expected []string
|
|
|
|
defaults []string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
fixture: "fixtures/resolv.conf.1",
|
|
|
|
defaults: []string{"127.0.0.1:53"},
|
|
|
|
expected: []string{"10.200.3.249:53", "10.200.3.250:5353", "[2001:4860:4860::8844]:53", "[10.0.0.1]:5353"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
fixture: "fixtures/resolv.conf.nonexistant",
|
|
|
|
defaults: []string{"127.0.0.1:53"},
|
|
|
|
expected: []string{"127.0.0.1:53"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range testCases {
|
|
|
|
t.Run(test.fixture, func(t *testing.T) {
|
|
|
|
result := getNameservers(test.fixture, test.defaults)
|
|
|
|
|
|
|
|
sort.Strings(result)
|
|
|
|
sort.Strings(test.expected)
|
|
|
|
|
|
|
|
assert.Equal(t, test.expected, result)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2024-02-11 13:37:09 +00:00
|
|
|
|
|
|
|
func TestDNSError_Error(t *testing.T) {
|
|
|
|
msgIn := createDNSMsg("example.com.", dns.TypeTXT, true)
|
|
|
|
|
|
|
|
msgOut := createDNSMsg("example.org.", dns.TypeSOA, true)
|
|
|
|
msgOut.Rcode = dns.RcodeNameError
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
desc string
|
|
|
|
err *DNSError
|
|
|
|
expected string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "empty error",
|
|
|
|
err: &DNSError{},
|
|
|
|
expected: "DNS error",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "all fields",
|
|
|
|
err: &DNSError{
|
|
|
|
Message: "Oops",
|
|
|
|
NS: "example.com.",
|
|
|
|
MsgIn: msgIn,
|
|
|
|
MsgOut: msgOut,
|
|
|
|
Err: errors.New("I did it again"),
|
|
|
|
},
|
|
|
|
expected: "Oops: I did it again [ns=example.com., question='example.com. IN TXT', code=NXDOMAIN]",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "only NS",
|
|
|
|
err: &DNSError{
|
|
|
|
NS: "example.com.",
|
|
|
|
},
|
|
|
|
expected: "DNS error [ns=example.com.]",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "only MsgIn",
|
|
|
|
err: &DNSError{
|
|
|
|
MsgIn: msgIn,
|
|
|
|
},
|
|
|
|
expected: "DNS error [question='example.com. IN TXT']",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "only MsgOut",
|
|
|
|
err: &DNSError{
|
|
|
|
MsgOut: msgOut,
|
|
|
|
},
|
|
|
|
expected: "DNS error [question='example.org. IN SOA', code=NXDOMAIN]",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "only Err",
|
|
|
|
err: &DNSError{
|
|
|
|
Err: errors.New("I did it again"),
|
|
|
|
},
|
|
|
|
expected: "DNS error: I did it again",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range testCases {
|
|
|
|
test := test
|
|
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
assert.EqualError(t, test.err, test.expected)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|