func FindZoneByFqdn(fqdn string) (string, error) {
	return FindZoneByFqdnCustom(fqdn, recursiveNameservers)
}
FindZoneByFqdn determines the zone apex for the given fqdn
by recursing up the domain labels until the nameserver returns a SOA record in the answer section.
package dns01
import (
	"errors"
	"fmt"
	"net"
	"strings"
	"sync"
	"time"
	"github.com/miekg/dns"
)
const defaultResolvConf = "/etc/resolv.conf"
var dnsTimeout = 10 * time.Second
var (
	fqdnSoaCache   = map[string]*soaCacheEntry{}
	muFqdnSoaCache sync.Mutex
)
var defaultNameservers = []string{
	"google-public-dns-a.google.com:53",
	"google-public-dns-b.google.com:53",
}
var recursiveNameservers = getNameservers(defaultResolvConf, defaultNameservers)
type soaCacheEntry struct {
	zone      string     
	primaryNs string     
	expires   time.Time  
}
func newSoaCacheEntry(soa *dns.SOA) *soaCacheEntry {
	return &soaCacheEntry{
		zone:      soa.Hdr.Name,
		primaryNs: soa.Ns,
		expires:   time.Now().Add(time.Duration(soa.Refresh) * time.Second),
	}
}
func (cache *soaCacheEntry) isExpired() bool {
	return time.Now().After(cache.expires)
}
func ClearFqdnCache() {
	muFqdnSoaCache.Lock()
	fqdnSoaCache = map[string]*soaCacheEntry{}
	muFqdnSoaCache.Unlock()
}
func AddDNSTimeout(timeout time.Duration) ChallengeOption {
	return func(_ *Challenge) error {
		dnsTimeout = timeout
		return nil
	}
}
func AddRecursiveNameservers(nameservers []string) ChallengeOption {
	return func(_ *Challenge) error {
		recursiveNameservers = ParseNameservers(nameservers)
		return nil
	}
}
func getNameservers(path string, defaults []string) []string {
	config, err := dns.ClientConfigFromFile(path)
	if err != nil || len(config.Servers) == 0 {
		return defaults
	}
	return ParseNameservers(config.Servers)
}
func ParseNameservers(servers []string) []string {
	var resolvers []string
	for _, resolver := range servers {
		if _, _, err := net.SplitHostPort(resolver); err != nil {
			resolvers = append(resolvers, net.JoinHostPort(resolver, "53"))
		} else {
			resolvers = append(resolvers, resolver)
		}
	}
	return resolvers
}
func lookupNameservers(fqdn string) ([]string, error) {
	var authoritativeNss []string
	zone, err := FindZoneByFqdn(fqdn)
	if err != nil {
		return nil, fmt.Errorf("could not determine the zone: %w", err)
	}
	r, err := dnsQuery(zone, dns.TypeNS, recursiveNameservers, true)
	if err != nil {
		return nil, err
	}
	for _, rr := range r.Answer {
		if ns, ok := rr.(*dns.NS); ok {
			authoritativeNss = append(authoritativeNss, strings.ToLower(ns.Ns))
		}
	}
	if len(authoritativeNss) > 0 {
		return authoritativeNss, nil
	}
	return nil, errors.New("could not determine authoritative nameservers")
}
func FindPrimaryNsByFqdn(fqdn string) (string, error) {
	return FindPrimaryNsByFqdnCustom(fqdn, recursiveNameservers)
}
func FindPrimaryNsByFqdnCustom(fqdn string, nameservers []string) (string, error) {
	soa, err := lookupSoaByFqdn(fqdn, nameservers)
	if err != nil {
		return "", err
	}
	return soa.primaryNs, nil
}