Exemple #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
}
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
}
Exemple #3
0
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
}
Exemple #4
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
}
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
}
Exemple #6
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)
	}
}
Exemple #8
0
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")
}
Exemple #9
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
}
//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
}