func dnsQuery(r *dns.Msg) (*dns.Msg, error) { dnsServers := GConf.LocalDNS.TrustedDNS var record *dnsCacheRecord var domain string useTrustedDNS := true if len(r.Question) == 1 && dns.IsFqdn(r.Question[0].Name) { domain = r.Question[0].Name domain = domain[0 : len(domain)-1] if nil != dnsCache { item, exist := dnsCache.Get(domain) if exist { record = item.(*dnsCacheRecord) if time.Now().After(record.expireAt) { record = nil dnsCache.Remove(domain) } else { if r.Question[0].Qtype == dns.TypeA && nil != record.ipv4Res { return record.ipv4Res, nil } else if r.Question[0].Qtype == dns.TypeAAAA && nil != record.ipv6Res { return record.ipv6Res, nil } } } } if nil != mygfwlist { connReq, _ := http.NewRequest("CONNECT", "https://"+domain, nil) isBlocked, _ := mygfwlist.FastMatchDoamin(connReq) if !isBlocked { dnsServers = GConf.LocalDNS.FastDNS useTrustedDNS = false } } } else { log.Printf("###DNS with %v", r.Question) } if len(dnsServers) == 0 { dnsServers = GConf.LocalDNS.TrustedDNS useTrustedDNS = true } if len(dnsServers) == 0 { log.Printf("At least one DNS server need to be configured in 'FastDNS/TrustedDNS'") return nil, errNoDNServer } server := selectDNSServer(dnsServers) network := "udp" if GConf.LocalDNS.TCPConnect && useTrustedDNS { network = "tcp" } log.Printf("DNS query %s to %s", domain, server) for retry := 0; retry < 3; retry++ { c, err := netx.DialTimeout(network, server, 1*time.Second) if nil != err { return nil, err } dnsConn := new(dns.Conn) if pc, ok := c.(getConnIntf); ok { c = pc.GetConn() } dnsConn.Conn = c dnsConn.WriteMsg(r) dnsConn.SetReadDeadline(time.Now().Add(1 * time.Second)) res, err1 := dnsConn.ReadMsg() if nil == err1 && nil != dnsCache && len(domain) > 0 { record = newDNSCacheRecord(record, res) dnsCache.Add(domain, record) } c.Close() if nil == err1 { return res, nil } } return nil, errDNSQuryFail }