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 }
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 }
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 }
// 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) } }
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") }
// 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 }