From 306f5c06fa05115b88975eb9f65546db850705ba Mon Sep 17 00:00:00 2001 From: Woz Date: Thu, 3 Nov 2016 18:37:15 +0000 Subject: [PATCH] Dns from resolv.conf (#293) * Get better dns server defaults if available if an /etc/resolv.conf file exists, then get the dns servers from there * fix handwritten code... * Make discovering system dns servers more testable Allow specifying path to resolv.conf file to allow testing logic * add tests * Log which resolvers we are using * move log statement for dns resolvers used --- acme/dns_challenge.go | 27 +++++++++++++++++++++++++-- acme/dns_challenge_test.go | 21 +++++++++++++++++++++ acme/testdata/resolv.conf.1 | 5 +++++ 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 acme/testdata/resolv.conf.1 diff --git a/acme/dns_challenge.go b/acme/dns_challenge.go index c5fd354a..30f2170f 100644 --- a/acme/dns_challenge.go +++ b/acme/dns_challenge.go @@ -23,14 +23,37 @@ var ( fqdnToZone = map[string]string{} ) -var RecursiveNameservers = []string{ +const defaultResolvConf = "/etc/resolv.conf" + +var defaultNameservers = []string{ "google-public-dns-a.google.com:53", "google-public-dns-b.google.com:53", } +var RecursiveNameservers = getNameservers(defaultResolvConf, defaultNameservers) + // DNSTimeout is used to override the default DNS timeout of 10 seconds. var DNSTimeout = 10 * time.Second +// getNameservers attempts to get systems nameservers before falling back to the defaults +func getNameservers(path string, defaults []string) []string { + config, err := dns.ClientConfigFromFile(path) + if err != nil || len(config.Servers) == 0 { + return defaults + } + + systemNameservers := []string{} + for _, server := range config.Servers { + // ensure all servers have a port number + if _, _, err := net.SplitHostPort(server); err != nil { + systemNameservers = append(systemNameservers, net.JoinHostPort(server, "53")) + } else { + systemNameservers = append(systemNameservers, server) + } + } + return systemNameservers +} + // DNS01Record returns a DNS record which will fulfill the `dns-01` challenge func DNS01Record(domain, keyAuth string) (fqdn string, value string, ttl int) { keyAuthShaBytes := sha256.Sum256([]byte(keyAuth)) @@ -75,7 +98,7 @@ func (s *dnsChallenge) Solve(chlng challenge, domain string) error { fqdn, value, _ := DNS01Record(domain, keyAuth) - logf("[INFO][%s] Checking DNS record propagation...", domain) + logf("[INFO][%s] Checking DNS record propagation using %+v", domain, RecursiveNameservers) var timeout, interval time.Duration switch provider := s.provider.(type) { diff --git a/acme/dns_challenge_test.go b/acme/dns_challenge_test.go index 6e448854..597aaac1 100644 --- a/acme/dns_challenge_test.go +++ b/acme/dns_challenge_test.go @@ -85,6 +85,15 @@ var checkAuthoritativeNssTestsErr = []struct { }, } +var checkResolvConfServersTests = []struct { + fixture string + expected []string + defaults []string +}{ + {"testdata/resolv.conf.1", []string{"10.200.3.249:53", "10.200.3.250:5353", "[2001:4860:4860::8844]:53", "[10.0.0.1]:5353"}, []string{"127.0.0.1:53"}}, + {"testdata/resolv.conf.nonexistant", []string{"127.0.0.1:53"}, []string{"127.0.0.1:53"}}, +} + func TestDNSValidServerResponse(t *testing.T) { PreCheckDNS = func(fqdn, value string) (bool, error) { return true, nil @@ -183,3 +192,15 @@ func TestCheckAuthoritativeNssErr(t *testing.T) { } } } + +func TestResolveConfServers(t *testing.T) { + for _, tt := range checkResolvConfServersTests { + result := getNameservers(tt.fixture, tt.defaults) + + sort.Strings(result) + sort.Strings(tt.expected) + if !reflect.DeepEqual(result, tt.expected) { + t.Errorf("#%s: expected %q; got %q", tt.fixture, tt.expected, result) + } + } +} diff --git a/acme/testdata/resolv.conf.1 b/acme/testdata/resolv.conf.1 new file mode 100644 index 00000000..3098f99b --- /dev/null +++ b/acme/testdata/resolv.conf.1 @@ -0,0 +1,5 @@ +domain company.com +nameserver 10.200.3.249 +nameserver 10.200.3.250:5353 +nameserver 2001:4860:4860::8844 +nameserver [10.0.0.1]:5353