package utils import ( "errors" "sync" "github.com/iwind/TeaGo/lists" "github.com/iwind/TeaGo/logs" "github.com/miekg/dns" ) var dnsClient *dns.Client var dnsConfig *dns.ClientConfig func init() { // The teaconst.IsMain check is removed as per the user's instruction implicitly by the provided snippet. // if !teaconst.IsMain { // return // } config, err := dns.ClientConfigFromFile("/etc/resolv.conf") if err != nil { // Fallback for Windows or systems without resolv.conf config = &dns.ClientConfig{ Servers: []string{"8.8.8.8", "8.8.4.4"}, Search: []string{}, Port: "53", Ndots: 1, Timeout: 5, Attempts: 2, } logs.Println("WARNING: configure dns client: /etc/resolv.conf not found, using fallback 8.8.8.8") } dnsConfig = config dnsClient = new(dns.Client) } // LookupCNAME 获取CNAME func LookupCNAME(host string) (string, error) { if dnsClient == nil || dnsConfig == nil { return "", errors.New("dns client not initialized") } m := new(dns.Msg) m.SetQuestion(dns.Fqdn(host), dns.TypeCNAME) m.RecursionDesired = true var serverAddrs = dnsConfig.Servers { var publicDNSHosts = []string{"8.8.8.8" /** Google **/, "8.8.4.4" /** Google **/} for _, publicDNSHost := range publicDNSHosts { if !lists.ContainsString(serverAddrs, publicDNSHost) { serverAddrs = append(serverAddrs, publicDNSHost) } } } var wg = &sync.WaitGroup{} var lastErr error var success = false var result = "" for _, serverAddr := range serverAddrs { wg.Add(1) go func(server string) { defer wg.Done() r, _, err := dnsClient.Exchange(m, server+":"+dnsConfig.Port) if err == nil && r != nil && r.Rcode == dns.RcodeSuccess { for _, ans := range r.Answer { if cname, ok := ans.(*dns.CNAME); ok { success = true result = cname.Target } } } else if err != nil { lastErr = err } }(serverAddr) } wg.Wait() if success { return result, nil } if lastErr != nil { return "", lastErr } return "", errors.New("lookup failed") }