diff --git a/acme/challenge.go b/acme/challenge.go index f11cdd945..c498fc57a 100644 --- a/acme/challenge.go +++ b/acme/challenge.go @@ -383,6 +383,7 @@ func dns01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebK vc := MustClientFromContext(ctx) txtRecords, err := vc.LookupTxt(dns01ChallengeHost(domain)) if err != nil { + logrus.Warnf("error looking up TXT records for domain %s: %v", domain, err) return storeError(ctx, db, ch, false, WrapError(ErrorDNSType, err, "error looking up TXT records for domain %s", domain)) } diff --git a/acme/client.go b/acme/client.go index 8f506ef95..b1f202409 100644 --- a/acme/client.go +++ b/acme/client.go @@ -3,8 +3,10 @@ package acme import ( "context" "crypto/tls" + "fmt" "net" "net/http" + "os" "time" ) @@ -45,8 +47,9 @@ func MustClientFromContext(ctx context.Context) Client { } type client struct { - http *http.Client - dialer *net.Dialer + http *http.Client + dialer *net.Dialer + resolver *net.Resolver } // NewClient returns an implementation of Client for verifying ACME challenges. @@ -65,15 +68,30 @@ func NewClient() Client { dialer: &net.Dialer{ Timeout: 30 * time.Second, }, + resolver: getResolver(), } } +func getResolver() *net.Resolver { + if os.Getenv("DNS_RESOLVER") != "" { + return &net.Resolver{ + PreferGo: true, + Dial: func(ctx context.Context, network, address string) (net.Conn, error) { + d := net.Dialer{ + Timeout: time.Millisecond * time.Duration(10000), + } + return d.DialContext(ctx, network, fmt.Sprintf("%s:53", os.Getenv("DNS_RESOLVER"))) + }} + } + return net.DefaultResolver +} + func (c *client) Get(url string) (*http.Response, error) { return c.http.Get(url) } func (c *client) LookupTxt(name string) ([]string, error) { - return net.LookupTXT(name) + return c.resolver.LookupTXT(context.Background(), name) } func (c *client) TLSDial(network, addr string, config *tls.Config) (*tls.Conn, error) {