diff --git a/challenge/dns01/client.go b/challenge/dns01/client.go index 22a00a433..b91939a7f 100644 --- a/challenge/dns01/client.go +++ b/challenge/dns01/client.go @@ -56,12 +56,7 @@ func NewClient(opts *Options) *Client { } if len(opts.RecursiveNameservers) == 0 { - defaultNameservers := []string{ - "google-public-dns-a.google.com:53", - "google-public-dns-b.google.com:53", - } - - opts.RecursiveNameservers = getNameservers(defaultResolvConf, defaultNameservers) + opts.RecursiveNameservers = getNameservers(defaultResolvConf, opts.NetworkStack) } if opts.Timeout == 0 { @@ -69,7 +64,7 @@ func NewClient(opts *Options) *Client { } return &Client{ - recursiveNameservers: opts.RecursiveNameservers, + recursiveNameservers: parseNameservers(opts.RecursiveNameservers), authoritativeNSPort: "53", tcpClient: &dns.Client{ Net: opts.NetworkStack.Network("tcp"), diff --git a/challenge/dns01/client_nameservers.go b/challenge/dns01/client_nameservers.go index 9b0646185..8812e5bad 100644 --- a/challenge/dns01/client_nameservers.go +++ b/challenge/dns01/client_nameservers.go @@ -6,6 +6,7 @@ import ( "net" "strings" + "github.com/go-acme/lego/v5/challenge" "github.com/miekg/dns" ) @@ -82,13 +83,33 @@ func (c *Client) lookupAuthoritativeNameservers(ctx context.Context, fqdn string } // getNameservers attempts to get systems nameservers before falling back to the defaults. -func getNameservers(path string, defaults []string) []string { +func getNameservers(path string, stack challenge.NetworkStack) []string { config, err := dns.ClientConfigFromFile(path) - if err != nil || len(config.Servers) == 0 { - return defaults + if err == nil && len(config.Servers) > 0 { + return config.Servers } - return parseNameservers(config.Servers) + switch stack { + case challenge.IPv4Only: + return []string{ + "1.1.1.1:53", + "1.0.0.1:53", + } + + case challenge.IPv6Only: + return []string{ + "[2606:4700:4700::1111]:53", + "[2606:4700:4700::1001]:53", + } + + default: + return []string{ + "1.1.1.1:53", + "1.0.0.1:53", + "[2606:4700:4700::1111]:53", + "[2606:4700:4700::1001]:53", + } + } } func parseNameservers(servers []string) []string { diff --git a/challenge/dns01/client_nameservers_test.go b/challenge/dns01/client_nameservers_test.go index 8df39042c..16e9f4a9f 100644 --- a/challenge/dns01/client_nameservers_test.go +++ b/challenge/dns01/client_nameservers_test.go @@ -4,6 +4,7 @@ import ( "sort" "testing" + "github.com/go-acme/lego/v5/challenge" "github.com/go-acme/lego/v5/platform/tester/dnsmock" "github.com/miekg/dns" "github.com/stretchr/testify/assert" @@ -185,27 +186,42 @@ func TestClient_lookupAuthoritativeNameservers_error(t *testing.T) { } } -func Test_getNameservers_ResolveConfServers(t *testing.T) { +func Test_getNameservers(t *testing.T) { testCases := []struct { - fixture string + desc string + path string + stack challenge.NetworkStack 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"}, + desc: "with resolv.conf", + path: "fixtures/resolv.conf.1", + stack: challenge.DualStack, + expected: []string{"10.200.3.249", "10.200.3.250:5353", "2001:4860:4860::8844", "[10.0.0.1]:5353"}, }, { - fixture: "fixtures/resolv.conf.nonexistant", - defaults: []string{"127.0.0.1:53"}, - expected: []string{"127.0.0.1:53"}, + desc: "with nonexistent resolv.conf", + path: "fixtures/resolv.conf.nonexistant", + stack: challenge.DualStack, + expected: []string{"1.0.0.1:53", "1.1.1.1:53", "[2606:4700:4700::1001]:53", "[2606:4700:4700::1111]:53"}, + }, + { + desc: "default with IPv4Only", + path: "resolv.conf.nonexistant", + stack: challenge.IPv4Only, + expected: []string{"1.0.0.1:53", "1.1.1.1:53"}, + }, + { + desc: "default with IPv6Only", + path: "resolv.conf.nonexistant", + stack: challenge.IPv6Only, + expected: []string{"[2606:4700:4700::1001]:53", "[2606:4700:4700::1111]:53"}, }, } for _, test := range testCases { - t.Run(test.fixture, func(t *testing.T) { - result := getNameservers(test.fixture, test.defaults) + t.Run(test.desc, func(t *testing.T) { + result := getNameservers(test.path, test.stack) sort.Strings(result) sort.Strings(test.expected) @@ -214,3 +230,32 @@ func Test_getNameservers_ResolveConfServers(t *testing.T) { }) } } + +func Test_parseNameservers(t *testing.T) { + testCases := []struct { + desc string + servers []string + expected []string + }{ + { + desc: "without explicit port", + servers: []string{"ns1.example.com", "2001:db8::1"}, + expected: []string{"ns1.example.com:53", "[2001:db8::1]:53"}, + }, + { + desc: "with explicit port", + servers: []string{"ns1.example.com:53", "[2001:db8::1]:53"}, + expected: []string{"ns1.example.com:53", "[2001:db8::1]:53"}, + }, + } + + for _, test := range testCases { + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + result := parseNameservers(test.servers) + + assert.Equal(t, test.expected, result) + }) + } +}