Example #1
0
func LookupIP(domain string, timeout int) ([]string, error) {
	var c dns.Client
	var err error
	ips := []string{}
	domain = strings.TrimRight(domain, ".") + "."
	c.DialTimeout = time.Duration(timeout) * time.Millisecond
	c.ReadTimeout = time.Duration(timeout) * time.Millisecond
	c.WriteTimeout = time.Duration(timeout) * time.Millisecond

	m := new(dns.Msg)
	m.SetQuestion(domain, dns.TypeA)

	ret, _, err := c.Exchange(m, "114.114.114.114:53")
	if err != nil {
		domain = strings.TrimRight(domain, ".")
		e := fmt.Sprintf("lookup error: %s, %s", domain, err.Error())
		return ips, errors.New(e)
	}

	for _, i := range ret.Answer {
		result := strings.Split(i.String(), "\t")
		if result[3] == "A" && IsIP(result[4]) {
			ips = append(ips, result[4])
		}
	}
	return ips, err
}
Example #2
0
// NewDNSResolverImpl constructs a new DNS resolver object that utilizes the
// provided list of DNS servers for resolution.
func NewDNSResolverImpl(
	readTimeout time.Duration,
	servers []string,
	caaSERVFAILExceptions map[string]bool,
	stats metrics.Scope,
	clk clock.Clock,
	maxTries int,
) *DNSResolverImpl {
	// TODO(jmhodges): make constructor use an Option func pattern
	dnsClient := new(dns.Client)

	// Set timeout for underlying net.Conn
	dnsClient.ReadTimeout = readTimeout
	dnsClient.Net = "tcp"

	return &DNSResolverImpl{
		dnsClient:                dnsClient,
		servers:                  servers,
		allowRestrictedAddresses: false,
		caaSERVFAILExceptions:    caaSERVFAILExceptions,
		maxTries:                 maxTries,
		clk:                      clk,
		stats:                    stats,
		txtStats:                 stats.NewScope("TXT"),
		aStats:                   stats.NewScope("A"),
		aaaaStats:                stats.NewScope("AAAA"),
		caaStats:                 stats.NewScope("CAA"),
		mxStats:                  stats.NewScope("MX"),
	}
}
Example #3
0
func (this Server) DoDNSquery(m dns.Msg, TransProString string, server []string, timeout time.Duration) (*dns.Msg, error) {
	dnsClient := new(dns.Client)
	if dnsClient == nil {
		return nil, errors.New("Cannot create DNS client")
	}

	dnsClient.ReadTimeout = timeout
	dnsClient.WriteTimeout = timeout
	if TransProString != "TCP" && TransProString != "UDP" {
		return nil, errors.New("TransProString run")
	}
	dnsClient.Net = strings.ToLower(TransProString)
	ServerStr := server[rand.Intn(len(server))]
	ServerAddr := net.ParseIP(ServerStr)
	if ServerAddr.To16() != nil {
		ServerStr = "[" + ServerStr + "]:" + this.Port
	} else if ServerAddr.To4() != nil {
		ServerStr = ServerStr + this.Port
	} else {
		return nil, errors.New("invalid Server Address")
	}
	dnsResponse, _, err := dnsClient.Exchange(&m, ServerStr)
	if err != nil {
		return nil, err
	}
	return dnsResponse, nil
}
Example #4
0
func localQuery(mychan chan DNSreply, qname string, qtype uint16) {
	var result DNSreply
	var trials uint
	result.qname = qname
	result.qtype = qtype
	result.r = nil
	result.err = errors.New("No name server to answer the question")
	localm := new(dns.Msg)
	localm.Id = dns.Id()
	localm.RecursionDesired = true
	localm.Question = make([]dns.Question, 1)
	localm.SetEdns0(EDNSBUFFERSIZE, false) // Even if no EDNS requested, see #9 May be we should retry without it if timeout?
	localc := new(dns.Client)
	localc.ReadTimeout = timeout
	localm.Question[0] = dns.Question{qname, qtype, dns.ClassINET}
Tests:
	for trials = 0; trials < uint(*maxTrials); trials++ {
	Resolvers:
		for serverIndex := range conf.Servers {
			server := conf.Servers[serverIndex]
			result.nameserver = server
			// Brackets around the server address are necessary for IPv6 name servers
			r, rtt, err := localc.Exchange(localm, "["+server+"]:"+conf.Port) // Do not use net.JoinHostPort, see https://github.com/bortzmeyer/check-soa/commit/3e4edb13855d8c4016768796b2892aa83eda1933#commitcomment-2355543
			if r == nil {
				result.r = nil
				result.err = err
				if strings.Contains(err.Error(), "timeout") {
					// Try another resolver
					break Resolvers
				} else { // We give in
					break Tests
				}
			} else {
				result.rtt = rtt
				if r.Rcode == dns.RcodeSuccess {
					// TODO: as a result, NODATA (NOERROR/ANSWER=0) are silently ignored (try "foo", for instance, the name exists but no IP address)
					// TODO: for rcodes like SERVFAIL, trying another resolver could make sense
					result.r = r
					result.err = nil
					break Tests
				} else {
					// All the other codes are errors. Yes, it may
					// happens that one resolver returns REFUSED
					// and the others work but we do not handle
					// this case. TODO: delete the resolver from
					// the list and try another one
					result.r = r
					result.err = errors.New(dns.RcodeToString[r.Rcode])
					break Tests
				}
			}
		}
	}
	if *debug {
		fmt.Printf("DEBUG: end of DNS request \"%s\" / %d\n", qname, qtype)
	}
	mychan <- result
}
Example #5
0
File: dns.go Project: fcavani/net
func lookupHost(host string, config *dns.ClientConfig) (addrs []string, err error) {
	if utilNet.IsValidIpv4(host) || utilNet.IsValidIpv6(host) {
		return []string{host}, nil
	}
	if host == "localhost" {
		return []string{"127.0.0.1", "::1"}, nil
	}

	c := new(dns.Client)
	c.DialTimeout = DialTimeout
	c.ReadTimeout = ReadTimeout
	c.WriteTimeout = WriteTimeout
	m := new(dns.Msg)
	m.SetQuestion(dns.Fqdn(host), dns.TypeA)
	var r *dns.Msg
	for i := 0; i < len(config.Servers); i++ {
		r, _, err = c.Exchange(m, config.Servers[i]+":"+config.Port)
		if err != nil {
			continue
		}
		err = nil
	}
	if err != nil {
		return nil, e.Forward(err)
	}
	if r.Rcode != dns.RcodeSuccess {
		return nil, e.New("can't resolve %v", host)
	}

	addrs = make([]string, 0, 10)
	for _, a := range r.Answer {
		if addr, ok := a.(*dns.A); ok {
			addrs = append(addrs, addr.A.String())
		}
	}

	m.SetQuestion(dns.Fqdn(host), dns.TypeAAAA)
	for i := 0; i < len(config.Servers); i++ {
		r, _, err = c.Exchange(m, config.Servers[0]+":"+config.Port)
		if err != nil {
			continue
		}
		err = nil
	}
	if err != nil {
		return nil, e.Forward(err)
	}
	if r.Rcode != dns.RcodeSuccess {
		return nil, e.New("no success")
	}

	for _, a := range r.Answer {
		if addr, ok := a.(*dns.AAAA); ok {
			addrs = append(addrs, addr.AAAA.String())
		}
	}
	return
}
Example #6
0
func (self *TrivialDnsServer) exchangeWithUpstream(r *dns.Msg) (*dns.Msg, time.Duration, error) {
	self.Count("upstream_queries")
	c := new(dns.Client)

	c.ReadTimeout = CommonTimeout
	c.WriteTimeout = CommonTimeout

	i := rand.Intn(len(self.Servers))
	upstreamServer := self.Servers[i]

	response, rtt, err := c.Exchange(r, upstreamServer)
	return response, rtt, err
}
Example #7
0
func (this ClientProxy) getServerIP() error {
	var dns_servers []string
	dnsClient := new(dns.Client)
	if dnsClient == nil {
		return errors.New("Can not new dns Client")
	}
	dnsClient.WriteTimeout = this.timeout
	dnsClient.ReadTimeout = this.timeout
	for _, serverstring := range this.SERVERS {
		ipaddress := net.ParseIP(serverstring)
		if ipaddress != nil {
			dns_servers = append(dns_servers, serverstring)
		} else {
			//used for unitest need to delete after test.
			/*if strings.EqualFold(serverstring, "example.com") {
				dns_servers = append(dns_servers, "127.0.0.1")
				continue
			}
			IPResult, err := net.LookupIP(serverstring)
			if err == nil {
				for _, appendStr := range IPResult {
					dns_servers = append(dns_servers, appendStr.String())
				}
			} else {

				return err
			}*/
			dnsResponse, err := searchServerIP(serverstring, 4, this.DNS_SERVERS)
			if err != nil {
				for i := 0; i < len(dnsResponse.Answer); i++ {
					dns_servers = append(dns_servers, dnsResponse.Answer[i].String())
				}
			} else {
				return err
			}
			dnsResponse, err = searchServerIP(serverstring, 6, this.DNS_SERVERS)
			if err == nil {
				for i := 0; i < len(dnsResponse.Answer); i++ {
					dns_servers = append(dns_servers, "["+dnsResponse.Answer[i].String()+"]")
				}
			} else {

				return err
			}
		}
	}
	this.SERVERS = dns_servers
	return nil
}
Example #8
0
// Returns true if domain has a Name Server associated
func queryNS(domain string, dnsServers []string, proto string) (int, error) {
	c := new(dns.Client)
	c.ReadTimeout = time.Duration(2 * time.Second)
	c.WriteTimeout = time.Duration(2 * time.Second)
	c.Net = proto
	m := new(dns.Msg)
	m.RecursionDesired = true
	dnsServer := dnsServers[rand.Intn(len(dnsServers))]
	m.SetQuestion(dns.Fqdn(domain), dns.TypeNS)
	in, _, err := c.Exchange(m, dnsServer+":53")
	if err == nil {
		return in.Rcode, err
	}
	return dns.RcodeRefused, err
}
// our ServeDNS interface, which gets invoked on every DNS message
func (this ServerProxy) ServeDNS(w dns.ResponseWriter, request *dns.Msg) {
	// see if we have our groovy custom EDNS0 option
	client_supports_appfrag := false
	opt := request.IsEdns0()
	if opt != nil {
		for ofs, e := range opt.Option {
			if e.Option() == dns.EDNS0LOCALSTART {
				_D("%s QID:%d found EDNS0LOCALSTART", w.RemoteAddr(), request.Id)
				client_supports_appfrag = true
				// go ahead and use the maximum UDP size for the local communication
				// with our server
				opt.SetUDPSize(65535)
				// remove the fragmentation option
				opt.Option = append(opt.Option[0:ofs], opt.Option[ofs+1:]...)
				// in principle we should only have one of these options
				break
			}
		}
	}

	// proxy the query
	c := new(dns.Client)
	c.ReadTimeout = this.timeout
	c.WriteTimeout = this.timeout
	response, rtt, err := c.Exchange(request, this.SERVERS[rand.Intn(this.s_len)])
	if err != nil {
		_D("%s QID:%d error proxying query: %s", w.RemoteAddr(), request.Id, err)
		this.SRVFAIL(w, request)
		return
	}
	_D("%s QID:%d request took %s", w.RemoteAddr(), request.Id, rtt)

	// if the client does not support fragmentation, we just send the response back and finish
	if !client_supports_appfrag {
		_D("%s QID:%d sending raw response to client", w.RemoteAddr(), request.Id)
		w.WriteMsg(response)
		return
	}

	// otherwise lets get our fragments
	all_frags := frag(response)

	// send our fragments
	for n, frag := range all_frags {
		_D("%s QID:%d sending fragment %d", w.RemoteAddr(), request.Id, n)
		w.WriteMsg(&frag)
	}
}
Example #10
0
File: dns.go Project: fcavani/net
func LookupIp(ip string) (host string, err error) {
	if !utilNet.IsValidIpv4(ip) && !utilNet.IsValidIpv6(ip) {
		return "", e.New("not a valid ip address")
	}
	if ip == "127.0.0.1" || ip == "::1" {
		return "localhost", nil
	}
	config, err := dns.ClientConfigFromFile(ConfigurationFile)
	if err != nil {
		return "", e.Forward(err)
	}
	config.Timeout = Timeout

	c := new(dns.Client)
	c.DialTimeout = DialTimeout
	c.ReadTimeout = ReadTimeout
	c.WriteTimeout = WriteTimeout
	m := new(dns.Msg)
	rev, err := dns.ReverseAddr(ip)
	if err != nil {
		return "", e.Forward(err)
	}
	m.SetQuestion(rev, dns.TypePTR)
	var r *dns.Msg
	for i := 0; i < len(config.Servers); i++ {
		r, _, err = c.Exchange(m, config.Servers[i]+":"+config.Port)
		if err != nil {
			continue
		}
		err = nil
	}
	if err != nil {
		return "", e.Forward(err)
	}
	if r.Rcode != dns.RcodeSuccess {
		return "", e.New("can't resolve %v", ip)
	}

	for _, a := range r.Answer {
		if ptr, ok := a.(*dns.PTR); ok {
			return strings.TrimSuffix(ptr.Ptr, "."), nil
		}
	}
	return "", e.New("no ptr available")
}
Example #11
0
// defaultExtResolver queries other nameserver, potentially recurses; callers should probably be invoking extResolver
// instead since that's the pluggable entrypoint into external resolution.
func (res *Resolver) defaultExtResolver(r *dns.Msg, nameserver string, proto string, cnt int) (*dns.Msg, error) {
	var in *dns.Msg
	var err error

	c := new(dns.Client)
	c.Net = proto

	var t time.Duration = 5 * 1e9
	if res.config.Timeout != 0 {
		t = time.Duration(int64(res.config.Timeout * 1e9))
	}

	c.DialTimeout = t
	c.ReadTimeout = t
	c.WriteTimeout = t

	in, _, err = c.Exchange(r, nameserver)
	if err != nil {
		return in, err
	}

	// recurse
	if (in != nil) && (len(in.Answer) == 0) && (!in.MsgHdr.Authoritative) && (len(in.Ns) > 0) && (err != nil) {

		if cnt == recurseCnt {
			logging.CurLog.NonMesosRecursed.Inc()
		}

		if cnt > 0 {
			if soa, ok := (in.Ns[0]).(*dns.SOA); ok {
				return res.defaultExtResolver(r, net.JoinHostPort(soa.Ns, "53"), proto, cnt-1)
			}
		}

	}

	return in, err
}
Example #12
0
func testSoa(msg *dns.Msg, server string, tries uint) (soa *dns.Msg, err error) {
	c := new(dns.Client)
	c.ReadTimeout = timeout * 1e9
	tests := uint(0)
	over := false
	for !over {
		soa, _, err = c.Exchange(msg, server)
		if err != nil {
			if e, ok := err.(net.Error); ok && e.Timeout() {
				tests++
				if tests < tries {
					continue
				} else {
					over = true
				}
			} else {
				over = true
			}
		} else {
			over = true
		}
	}
	return soa, err
}
Example #13
0
func (d *DnsQuery) getDnsQueryTime(domain string, server string) (float64, error) {
	dnsQueryTime := float64(0)

	c := new(dns.Client)
	c.ReadTimeout = time.Duration(d.Timeout) * time.Second

	m := new(dns.Msg)
	recordType, err := d.parseRecordType()
	if err != nil {
		return dnsQueryTime, err
	}
	m.SetQuestion(dns.Fqdn(domain), recordType)
	m.RecursionDesired = true

	r, rtt, err := c.Exchange(m, net.JoinHostPort(server, strconv.Itoa(d.Port)))
	if err != nil {
		return dnsQueryTime, err
	}
	if r.Rcode != dns.RcodeSuccess {
		return dnsQueryTime, errors.New(fmt.Sprintf("Invalid answer name %s after %s query for %s\n", domain, d.RecordType, domain))
	}
	dnsQueryTime = float64(rtt.Nanoseconds()) / 1e6
	return dnsQueryTime, nil
}
Example #14
0
func main() {
	var err error
	if len(os.Args) != 2 {
		fmt.Printf("%s ZONE\n", os.Args[0])
		os.Exit(1)
	}
	conf, err = dns.ClientConfigFromFile("/etc/resolv.conf")
	if conf == nil {
		fmt.Printf("Cannot initialize the local resolver: %s\n", err)
		os.Exit(1)
	}
	localm = new(dns.Msg)
	localm.RecursionDesired = true
	localm.Question = make([]dns.Question, 1)
	localc = new(dns.Client)
	localc.ReadTimeout = TIMEOUT * 1e9
	r, err := localQuery(dns.Fqdn(os.Args[1]), dns.TypeNS)
	if r == nil {
		fmt.Printf("Cannot retrieve the list of name servers for %s: %s\n", dns.Fqdn(os.Args[1]), err)
		os.Exit(1)
	}
	if r.Rcode == dns.RcodeNameError {
		fmt.Printf("No such domain %s\n", dns.Fqdn(os.Args[1]))
		os.Exit(1)
	}
	m := new(dns.Msg)
	m.RecursionDesired = false
	m.Question = make([]dns.Question, 1)
	c := new(dns.Client)
	c.ReadTimeout = TIMEOUT * 1e9
	success := true
	numNS := 0
	for _, ans := range r.Answer {
		switch ans.(type) {
		case *dns.NS:
			nameserver := ans.(*dns.NS).Ns
			numNS += 1
			ips := make([]string, 0)
			fmt.Printf("%s : ", nameserver)
			ra, err := localQuery(nameserver, dns.TypeA)
			if ra == nil {
				fmt.Printf("Error getting the IPv4 address of %s: %s\n", nameserver, err)
				os.Exit(1)
			}
			if ra.Rcode != dns.RcodeSuccess {
				fmt.Printf("Error getting the IPv4 address of %s: %s\n", nameserver, dns.RcodeToString[ra.Rcode])
				os.Exit(1)
			}
			for _, ansa := range ra.Answer {
				switch ansa.(type) {
				case *dns.A:
					ips = append(ips, ansa.(*dns.A).A.String())
				}
			}
			raaaa, err := localQuery(nameserver, dns.TypeAAAA)
			if raaaa == nil {
				fmt.Printf("Error getting the IPv6 address of %s: %s\n", nameserver, err)
				os.Exit(1)
			}
			if raaaa.Rcode != dns.RcodeSuccess {
				fmt.Printf("Error getting the IPv6 address of %s: %s\n", nameserver, dns.RcodeToString[raaaa.Rcode])
				os.Exit(1)
			}
			for _, ansaaaa := range raaaa.Answer {
				switch ansaaaa.(type) {
				case *dns.AAAA:
					ips = append(ips, ansaaaa.(*dns.AAAA).AAAA.String())
				}
			}
			if len(ips) == 0 {
				success = false
				fmt.Printf("No IP address for this server")
			}
			for _, ip := range ips {
				m.Question[0] = dns.Question{dns.Fqdn(os.Args[1]), dns.TypeSOA, dns.ClassINET}
				nsAddressPort := ""
				if strings.ContainsAny(":", ip) {
					// IPv6 address
					nsAddressPort = "[" + ip + "]:53"
				} else {
					nsAddressPort = ip + ":53"
				}
				soa, _, err := c.Exchange(m, nsAddressPort)
				// TODO: retry if timeout? Otherwise, one lost UDP packet and it is the end
				if soa == nil {
					success = false
					fmt.Printf("%s (%s) ", ip, err)
					goto Next
				}
				if soa.Rcode != dns.RcodeSuccess {
					success = false
					fmt.Printf("%s (%s) ", ips, dns.RcodeToString[soa.Rcode])
					goto Next
				}
				if len(soa.Answer) == 0 { // May happen if the server is a recursor, not authoritative, since we query with RD=0
					success = false
					fmt.Printf("%s (0 answer) ", ip)
					goto Next
				}
				rsoa := soa.Answer[0]
				switch rsoa.(type) {
				case *dns.SOA:
					if soa.Authoritative {
						// TODO: test if all name servers have the same serial ?
						fmt.Printf("%s (%d) ", ips, rsoa.(*dns.SOA).Serial)
					} else {
						success = false
						fmt.Printf("%s (not authoritative) ", ips)
					}
				}
			}
		Next:
			fmt.Printf("\n")
		}
	}
	if numNS == 0 {
		fmt.Printf("No NS records for \"%s\". It is probably a CNAME to a domain but not a zone\n", dns.Fqdn(os.Args[1]))
		os.Exit(1)
	}
	if success {
		os.Exit(0)
	}
	os.Exit(1)
}
Example #15
0
func sendNotify(servers []string, domain string) []NotifyResponse {

	if !strings.HasSuffix(domain, ".") {
		domain = domain + "."
	}

	if len(servers) == 0 {
		fmt.Println("No servers")
		resp := NotifyResponse{Result: "No servers", Error: true}
		fmt.Println("No servers")
		return []NotifyResponse{resp}
	}

	c := new(dns.Client)

	c.ReadTimeout = time.Duration(*timeout) * time.Millisecond

	m := new(dns.Msg)
	m.SetNotify(domain)

	wg := new(sync.WaitGroup)

	responseChannel := make(chan NotifyResponse, len(servers))

	for _, server := range servers {

		go func(server string) {

			result := NotifyResponse{Server: server}

			wg.Add(1)

			defer func() {
				wg.Done()
				if result.Error || !*quiet {
					fmt.Printf("%s: %s\n", result.Server, result.Result)
				}
				responseChannel <- result
			}()

			target, err := fixupHost(server)
			if err != nil {
				result.Result = fmt.Sprintf("%s: %s", server, err)
				fmt.Println(result.Result)
				result.Error = true
				return
			}

			result.Server = target

			if *verbose {
				fmt.Println("Sending notify to", target)
			}

			resp, rtt, err := c.Exchange(m, target)

			if err != nil {
				result.Error = true
				result.Result = err.Error()
				return
			}

			ok := "ok"
			if !resp.Authoritative {
				ok = fmt.Sprintf("not ok (%s)", dns.RcodeToString[resp.Rcode])
			}

			result.Result = fmt.Sprintf("%s: %s (%s)",
				target, ok, rtt.String())

			responseChannel <- result
		}(server)

	}

	responses := make([]NotifyResponse, len(servers))

	for i := 0; i < len(servers); i++ {
		responses[i] = <-responseChannel
	}

	wg.Wait()

	return responses

}
Example #16
0
func soaQuery(mychan chan SOAreply, zone string, name string, server string) {
	var result SOAreply
	var trials uint
	result.retrieved = false
	result.name = name
	result.address = server
	result.msg = "UNKNOWN"
	m := new(dns.Msg)
	if !*noedns {
		m.SetEdns0(EDNSBUFFERSIZE, !*nodnssec)
	}
	m.Id = dns.Id()
	if *recursion {
		m.RecursionDesired = true
	} else {
		m.RecursionDesired = false
	}
	m.Question = make([]dns.Question, 1)
	c := new(dns.Client)
	c.ReadTimeout = timeout // Seems ignored for TCP?
	if *tcp {
		c.Net = "tcp"
	}
	m.Question[0] = dns.Question{zone, dns.TypeSOA, dns.ClassINET}
	nsAddressPort := ""
	nsAddressPort = net.JoinHostPort(server, "53")
	if *debug {
		fmt.Printf("DEBUG Querying SOA from %s\n", nsAddressPort)
	}
	for trials = 0; trials < uint(*maxTrials); trials++ {
		soa, rtt, err := c.Exchange(m, nsAddressPort)
		if soa == nil {
			result.rtt = 0
			result.msg = fmt.Sprintf("%s", err.Error())
		} else {
			result.rtt = rtt
			if soa.Rcode != dns.RcodeSuccess {
				result.msg = dns.RcodeToString[soa.Rcode]
				break
			} else {
				if len(soa.Answer) == 0 { /* May happen if the server is a recursor, not authoritative, since we query with RD=0 */
					result.msg = "0 answer"
					break
				} else {
					gotSoa := false
					for _, rsoa := range soa.Answer {
						switch rsoa.(type) {
						case *dns.SOA:
							if *noauthrequired || soa.MsgHdr.Authoritative {
								result.retrieved = true
								result.serial = rsoa.(*dns.SOA).Serial
								result.msg = "OK"
							} else {
								result.msg = "Not authoritative"
							}
							gotSoa = true
						case *dns.CNAME: /* Bad practice but common */
							fmt.Printf("Apparently not a zone but an alias\n")
							os.Exit(1)
						case *dns.RRSIG:
							/* Ignore them. See bug #8 */
						default:
							// TODO: a name server can send us other RR types.
							fmt.Printf("Internal error when processing %s, unexpected record type\n", rsoa)
							os.Exit(1)
						}
					}
					if !gotSoa {
						result.msg = "No SOA record in reply"
					}
					break
				}
			}
			break // We got a reply
		}
	}
	mychan <- result
}
//not sure how to make a server fail, error 501?
func (this Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	TransProString := r.Header.Get("X-Proxy-DNS-Transport")
	if TransProString == "tcp" {
		this.TransPro = TCPcode
	} else if TransProString == "udp" {
		this.TransPro = UDPcode
	} else {
		_D("Transport protol not udp or tcp")
		http.Error(w, "unknown transport protocol", 415)
		return
	}
	contentTypeStr := r.Header.Get("Content-Type")
	if contentTypeStr != "application/X-DNSoverHTTP" {
		_D("Content-Type illegal")
		http.Error(w, "unknown content type", 415)
		return
	}
	var requestBody []byte
	requestBody, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "error in reading request", 400)
		_D("error in reading HTTP request, error message: %s", err)
		return
	}
	if len(requestBody) < (int)(r.ContentLength) {
		http.Error(w, "error in reading request", 400)
		_D("fail to read all HTTP content")
		return
	}
	var dnsRequest dns.Msg
	err = dnsRequest.Unpack(requestBody)
	if err != nil {
		http.Error(w, "bad DNS request", 400)
		_D("error in packing HTTP response to DNS, error message: %s", err)
		return
	}
	dnsClient := new(dns.Client)
	if dnsClient == nil {
		http.Error(w, "Server Error", 500)
		_D("cannot create DNS client")
		return
	}
	dnsClient.ReadTimeout = this.timeout
	dnsClient.WriteTimeout = this.timeout
	dnsClient.Net = TransProString
	//will use a parameter to let user address resolver in future
	dnsResponse, RTT, err := dnsClient.Exchange(&dnsRequest, this.SERVERS[rand.Intn(len(this.SERVERS))])
	//dnsResponse, RTT, err := dnsClient.Exchange(&dnsRequest, this.SERVERS[0])
	if err != nil {
		_D("error in communicate with resolver, error message: %s", err)
		http.Error(w, "Server Error", 500)
		return
	} else {
		_D("request took %s", RTT)
	}
	if dnsResponse == nil {
		_D("no response back")
		http.Error(w, "Server Error:No Recursive response", 500)
		return
	}
	response_bytes, err := dnsResponse.Pack()
	if err != nil {
		http.Error(w, "error packing reply", 500)
		_D("error in packing request, error message: %s", err)
		return
	}
	_, err = w.Write(response_bytes)
	if err != nil {
		_D("Can not write response rightly, error message: %s", err)
		return
	}
	//don't know how to creat a response here
}