Esempio n. 1
0
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
}