Beispiel #1
0
// Performs the actual query by service name (browse) or service instance name (lookup),
// start response listeners goroutines and loops over the entries channel.
func (c *client) query(params *LookupParams) error {
	var serviceName, serviceInstanceName string
	serviceName = fmt.Sprintf("%s.%s.", trimDot(params.Service), trimDot(params.Domain))
	if params.Instance != "" {
		serviceInstanceName = fmt.Sprintf("%s.%s", params.Instance, serviceName)
	}

	// send the query
	m := new(dns.Msg)
	if serviceInstanceName != "" {
		m.Question = []dns.Question{
			dns.Question{serviceInstanceName, dns.TypeSRV, dns.ClassINET},
			dns.Question{serviceInstanceName, dns.TypeTXT, dns.ClassINET},
		}
		m.RecursionDesired = false
	} else {
		m.SetQuestion(serviceName, dns.TypePTR)
		m.RecursionDesired = false
	}
	if err := c.sendQuery(m); err != nil {
		return err
	}

	return nil
}
Beispiel #2
0
func main() {
	if len(os.Args) <= 1 {
		log.Printf("Usage: %s domain", os.Args[0])
		os.Exit(1)
	}

	config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
	c := new(dns.Client)

	m := new(dns.Msg)
	m.SetQuestion(dns.Fqdn(os.Args[1]), dns.TypeMX)
	m.RecursionDesired = true

	r, _, err := c.Exchange(m, net.JoinHostPort(config.Servers[0], config.Port))
	if r == nil {
		log.Fatalf("*** error: %s\n", err.Error())
	}

	if r.Rcode != dns.RcodeSuccess {
		log.Fatalf(" *** invalid answer name %s after MX query for %s\n", os.Args[1], os.Args[1])
	}
	// Stuff must be in the answer section
	for _, a := range r.Answer {
		fmt.Printf("%v\n", a)
	}
}
Beispiel #3
0
// perform a DNS query and assert the reply code, number or answers, etc
func assertExchange(t *testing.T, z string, ty uint16, minAnswers int, maxAnswers int, expErr int) *dns.Msg {
	c := new(dns.Client)
	c.UDPSize = testUDPBufSize
	m := new(dns.Msg)
	m.RecursionDesired = true
	m.SetQuestion(z, ty)
	m.SetEdns0(testUDPBufSize, false) // we don't want to play with truncation here...

	r, _, err := c.Exchange(m, fmt.Sprintf("127.0.0.1:%d", testPort))
	t.Logf("Response:\n%+v\n", r)
	wt.AssertNoErr(t, err)
	if minAnswers == 0 && maxAnswers == 0 {
		wt.AssertStatus(t, r.Rcode, expErr, "DNS response code")
	} else {
		wt.AssertStatus(t, r.Rcode, dns.RcodeSuccess, "DNS response code")
	}
	answers := len(r.Answer)
	if minAnswers >= 0 && answers < minAnswers {
		wt.Fatalf(t, "Number of answers >= %d", minAnswers)
	}
	if maxAnswers >= 0 && answers > maxAnswers {
		wt.Fatalf(t, "Number of answers <= %d", maxAnswers)
	}
	return r
}
func (self *DnsResolver) lookupHost(host string, triesLeft int) ([]net.IP, error) {
	m1 := new(dns.Msg)
	m1.Id = dns.Id()
	m1.RecursionDesired = true
	m1.Question = make([]dns.Question, 1)
	m1.Question[0] = dns.Question{dns.Fqdn(host), dns.TypeA, dns.ClassINET}
	in, err := dns.Exchange(m1, self.Servers[self.r.Intn(len(self.Servers))])

	result := []net.IP{}

	if err != nil {
		if strings.HasSuffix(err.Error(), "i/o timeout") && triesLeft > 0 {
			triesLeft -= 1
			return self.lookupHost(host, triesLeft)
		} else {
			return result, err
		}
	}

	if in != nil && in.Rcode != dns.RcodeSuccess {
		return result, errors.New(dns.RcodeToString[in.Rcode])
	}

	for _, record := range in.Answer {
		if t, ok := record.(*dns.A); ok {
			result = append(result, t.A)
		}
	}
	return result, err
}
Beispiel #5
0
func (c *Client) Discover(domain string, cb func(*dns.Msg)) {
	m := new(dns.Msg)
	m.SetQuestion(dns.Fqdn(domain), dns.TypePTR)
	m.RecursionDesired = true

	addr := &net.UDPAddr{
		IP:   net.ParseIP("224.0.0.251"),
		Port: 5353,
	}

	conn, err := net.ListenMulticastUDP("udp4", nil, addr)

	if err != nil {
		panic(err)
	}

	defer conn.Close()
	c.conn = conn

	out, err := m.Pack()

	if err != nil {
		panic(err)
	}

	_, err = conn.WriteToUDP(out, addr)
	if err != nil {
		panic(err)
	}

	c.handleReceiveMsg(domain, cb)
}
Beispiel #6
0
// Perform a DNS query and assert the reply code, number or answers, etc
func assertExchange(t *testing.T, z string, ty uint16, port int, minAnswers int, maxAnswers int, expErr int) (*dns.Msg, *dns.Msg) {
	require.NotEqual(t, 0, port, "invalid DNS server port")

	c := &dns.Client{
		UDPSize: testUDPBufSize,
	}

	m := new(dns.Msg)
	m.RecursionDesired = true
	m.SetQuestion(z, ty)
	m.SetEdns0(testUDPBufSize, false) // we don't want to play with truncation here...

	lstAddr := fmt.Sprintf("127.0.0.1:%d", port)
	r, _, err := c.Exchange(m, lstAddr)
	t.Logf("Response from '%s':\n%+v\n", lstAddr, r)
	if err != nil {
		t.Errorf("Error when querying DNS server at %s: %s", lstAddr, err)
	}
	require.NoError(t, err)
	if minAnswers == 0 && maxAnswers == 0 {
		require.Equal(t, expErr, r.Rcode, "DNS response code")
	} else {
		require.Equal(t, dns.RcodeSuccess, r.Rcode, "DNS response code")
	}
	answers := len(r.Answer)
	if minAnswers >= 0 && answers < minAnswers {
		require.FailNow(t, fmt.Sprintf("Number of answers >= %d", minAnswers))
	}
	if maxAnswers >= 0 && answers > maxAnswers {
		require.FailNow(t, fmt.Sprintf("Number of answers <= %d", maxAnswers))
	}
	return m, r
}
Beispiel #7
0
// dnsQuery will query a nameserver, iterating through the supplied servers as it retries
// The nameserver should include a port, to facilitate testing where we talk to a mock dns server.
func dnsQuery(fqdn string, rtype uint16, nameservers []string, recursive bool) (in *dns.Msg, err error) {
	m := new(dns.Msg)
	m.SetQuestion(fqdn, rtype)
	m.SetEdns0(4096, false)

	if !recursive {
		m.RecursionDesired = false
	}

	// Will retry the request based on the number of servers (n+1)
	for i := 1; i <= len(nameservers)+1; i++ {
		ns := nameservers[i%len(nameservers)]
		udp := &dns.Client{Net: "udp", Timeout: DNSTimeout}
		in, _, err = udp.Exchange(m, ns)

		if err == dns.ErrTruncated {
			tcp := &dns.Client{Net: "tcp", Timeout: DNSTimeout}
			// If the TCP request suceeds, the err will reset to nil
			in, _, err = tcp.Exchange(m, ns)
		}

		if err == nil {
			break
		}
	}
	return
}
Beispiel #8
0
// Async
func (c *MDNSClient) SendQuery(name string, querytype uint16, insistent bool, responseCh chan<- *Response) {
	c.actionChan <- func() {
		query, found := c.inflight[name]
		if !found {
			m := new(dns.Msg)
			m.SetQuestion(name, querytype)
			m.RecursionDesired = false
			buf, err := m.Pack()
			if err != nil {
				responseCh <- &Response{err: err}
				close(responseCh)
				return
			}
			query = &inflightQuery{
				name: name,
				id:   m.Id,
			}
			if _, err = c.conn.WriteTo(buf, c.addr); err != nil {
				responseCh <- &Response{err: err}
				close(responseCh)
				return
			}
			c.inflight[name] = query
		}
		info := &responseInfo{
			ch:        responseCh,
			timeout:   time.Now().Add(mDNSTimeout),
			insistent: insistent,
		}
		// Invariant on responseInfos: they are in ascending order of
		// timeout.  Since we use a fixed interval from Now(), this
		// must be after all existing timeouts.
		query.responseInfos = append(query.responseInfos, info)
	}
}
Beispiel #9
0
func makeDnsTxtRequest(domain string, server string) (string, error) {
	var err error
	var conn *dns.Conn
	if conn, err = dns.Dial("udp", server); err != nil {
		return "", err
	}

	m := new(dns.Msg)
	m.SetQuestion(dns.Fqdn(domain), dns.TypeTXT)
	m.RecursionDesired = true

	if err = conn.WriteMsg(m); err != nil {
		return "", err
	}

	var rm *dns.Msg
	if rm, err = conn.ReadMsg(); err != nil {
		return "", err
	}

	if txt, ok := rm.Answer[0].(*dns.TXT); !ok {
		return "", fmt.Errorf("No TXT Answer")
	} else {
		return strings.Join(txt.Txt, ""), nil
	}

}
Beispiel #10
0
func createDKIMQuery(selector, domain string) *dns.Msg {
	q := fmt.Sprintf("%s._domainkey.%s", selector, domain)
	m := new(dns.Msg)
	m.SetQuestion(dns.Fqdn(q), dns.TypeTXT)
	m.RecursionDesired = true
	return m
}
Beispiel #11
0
// Check that we can prune an answer
func TestPrune(t *testing.T) {
	InitDefaultLogging(testing.Verbose())
	Info.Println("TestPrune starting")

	questionMsg := new(dns.Msg)
	questionMsg.SetQuestion("name", dns.TypeA)
	questionMsg.RecursionDesired = true
	question := &questionMsg.Question[0]
	records := []ZoneRecord{
		Record{"name", net.ParseIP("10.0.1.1"), 0, 0, 0},
		Record{"name", net.ParseIP("10.0.1.2"), 0, 0, 0},
		Record{"name", net.ParseIP("10.0.1.3"), 0, 0, 0},
		Record{"name", net.ParseIP("10.0.1.4"), 0, 0, 0},
	}

	reply := makeAddressReply(questionMsg, question, records, DefaultLocalTTL)
	reply.Answer[0].Header().Ttl = DefaultLocalTTL

	pruned := pruneAnswers(reply.Answer, 1)
	require.Equal(t, 1, len(pruned), "wrong number of answers")

	pruned = pruneAnswers(reply.Answer, 2)
	require.Equal(t, 2, len(pruned), "wrong number of answers")

	pruned = pruneAnswers(reply.Answer, 0)
	require.Equal(t, len(records), len(pruned), "wrong number of answers")
}
Beispiel #12
0
func DnsQuery(query string, wg *sync.WaitGroup, config *dns.ClientConfig, cm *chanman.ChanMan) {
	defer wg.Done()
	dnsClient := new(dns.Client)
	message := new(dns.Msg)
	message.SetQuestion(dns.Fqdn(query), dns.TypeA)
	message.RecursionDesired = true

	response, rtt, err := dnsClient.Exchange(message, net.JoinHostPort(config.Servers[0], "53"))

	if err != nil {
		log.Println(err)
		cm.RunChan <- true
	}

	if response == nil {
	} else {
		if response.Rcode != dns.RcodeSuccess {
			log.Println(" query fail")
		}
		var stat = new(dnsstat.Info)
		stat.Rtt = rtt
		cm.StatsChan <- stat
		cm.RunChan <- true
	}
}
Beispiel #13
0
func newMsg(host string, qClass uint16) *dns.Msg {
	m1 := new(dns.Msg)
	m1.Id = dns.Id()
	m1.RecursionDesired = true
	m1.Question = make([]dns.Question, 1)
	m1.Question[0] = dns.Question{host, qClass, dns.ClassINET}
	return m1
}
Beispiel #14
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
}
Beispiel #15
0
// Perform probing & announcement
//TODO: implement a proper probing & conflict resolution
func (s *Server) probe() {
	q := new(dns.Msg)
	q.SetQuestion(s.service.ServiceInstanceName(), dns.TypePTR)
	q.RecursionDesired = false

	srv := &dns.SRV{
		Hdr: dns.RR_Header{
			Name:   s.service.ServiceInstanceName(),
			Rrtype: dns.TypeSRV,
			Class:  dns.ClassINET,
			Ttl:    s.ttl,
		},
		Priority: 0,
		Weight:   0,
		Port:     uint16(s.service.Port),
		Target:   s.service.HostName,
	}
	txt := &dns.TXT{
		Hdr: dns.RR_Header{
			Name:   s.service.ServiceInstanceName(),
			Rrtype: dns.TypeTXT,
			Class:  dns.ClassINET,
			Ttl:    s.ttl,
		},
		Txt: s.service.Text,
	}
	q.Ns = []dns.RR{srv, txt}

	randomizer := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := 0; i < 3; i++ {
		if err := s.multicastResponse(q); err != nil {
			log.Println("[ERR] bonjour: failed to send probe:", err.Error())
		}
		time.Sleep(time.Duration(randomizer.Intn(250)) * time.Millisecond)
	}
	resp := new(dns.Msg)
	resp.MsgHdr.Response = true
	resp.Answer = []dns.RR{}
	resp.Extra = []dns.RR{}
	s.composeLookupAnswers(resp, s.ttl)

	// From RFC6762
	//    The Multicast DNS responder MUST send at least two unsolicited
	//    responses, one second apart. To provide increased robustness against
	//    packet loss, a responder MAY send up to eight unsolicited responses,
	//    provided that the interval between unsolicited responses increases by
	//    at least a factor of two with every response sent.
	timeout := 1 * time.Second
	for i := 0; i < 3; i++ {
		if err := s.multicastResponse(resp); err != nil {
			log.Println("[ERR] bonjour: failed to send announcement:", err.Error())
		}
		time.Sleep(timeout)
		timeout *= 2
	}
}
Beispiel #16
0
// DNS requests go to this function
func dnsHandle(w dns.ResponseWriter, r *dns.Msg) {
	name := r.Question[0].Name
	if !namePattern.MatchString(name) {
		kilog.Debug("%v does not match pattern, forwarding", name)
		dnsForward(w, r)
		return
	}
	// otherwise
	kilog.Debug("%v matches pattern, handling", name)
	dnsLock.Lock()
	defer dnsLock.Unlock()
	// check in table first
	fakeIP, ok := nameToIP[name]
	if !ok {
		// place in table
		var nwIP string
		for {
			haha := ipAlloc().String()
			_, exists := ipToName[haha]
			if exists {
				continue
			}
			nwIP = haha
			break
		}
		fakeIP = nwIP
		nameToIP[name] = fakeIP
		ipToName[fakeIP] = name
		// remove in 30 minutes
		go func() {
			time.Sleep(time.Minute * 30)
			dnsLock.Lock()
			defer dnsLock.Unlock()
			delete(nameToIP, name)
			delete(ipToName, fakeIP)
		}()
	}
	// return the fake IP to the user
	resp := new(dns.A)
	resp.Hdr.Name = name
	resp.Hdr.Ttl = 1 // very short
	resp.Hdr.Class = dns.ClassINET
	resp.Hdr.Rrtype = dns.TypeA
	resp.A = net.ParseIP(fakeIP)

	towrite := new(dns.Msg)
	towrite.Id = r.Id
	towrite.RecursionAvailable = true
	towrite.RecursionDesired = true
	towrite.Response = true
	towrite.Question = r.Question
	towrite.Answer = make([]dns.RR, 1)
	towrite.Answer[0] = resp
	w.WriteMsg(towrite)
	kilog.Debug("returning mapping %v -> %v", name, fakeIP)
}
Beispiel #17
0
func (d PodCheckAuth) authenticateToRegistry(token string, r types.DiagnosticResult) {
	resolvConf, err := getResolvConf(r)
	if err != nil {
		return // any errors have been reported via "r", env is very borked, test cannot proceed
	}
	msg := new(dns.Msg)
	msg.SetQuestion(registryHostname+".", dns.TypeA)
	msg.RecursionDesired = false
	result, completed := dnsQueryWithTimeout(msg, resolvConf.Servers[0], 2)
	switch {
	case !completed:
		r.Error("DP1006", nil, fmt.Sprintf("DNS resolution for registry address %s timed out; this could indicate problems with DNS resolution or networking", registryHostname))
		return
	case result.err != nil:
		r.Error("DP1016", nil, fmt.Sprintf("DNS resolution for registry address %s returned an error; container DNS is likely incorrect. The error was: %v", registryHostname, result.err))
		return
	case result.in == nil, len(result.in.Answer) == 0:
		r.Warn("DP1007", nil, fmt.Sprintf("DNS resolution for registry address %s returned no results; either the integrated registry is not deployed, or container DNS configuration is incorrect.", registryHostname))
		return
	}

	// first try the secure connection in case they followed directions to secure the registry
	// (https://docs.openshift.org/latest/install_config/install/docker_registry.html#securing-the-registry)
	cacert, err := ioutil.ReadFile(d.MasterCaPath) // TODO: we assume same CA as master - better choice?
	if err != nil {
		r.Error("DP1008", err, fmt.Sprintf("Failed to read CA cert file %s:\n%v", d.MasterCaPath, err))
		return
	}
	pool := x509.NewCertPool()
	if !pool.AppendCertsFromPEM(cacert) {
		r.Error("DP1009", err, fmt.Sprintf("Could not use cert from CA cert file %s:\n%v", d.MasterCaPath, err))
		return
	}
	noSecClient := http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return fmt.Errorf("no redirect expected")
		},
		Timeout: time.Second * 2,
	}
	secClient := noSecClient
	secClient.Transport = knet.SetTransportDefaults(&http.Transport{TLSClientConfig: &tls.Config{RootCAs: pool}})
	secError := processRegistryRequest(&secClient, fmt.Sprintf("https://%s:%s/v2/", registryHostname, registryPort), token, r)
	if secError == nil {
		return // made the request successfully enough to diagnose
	}
	switch {
	case strings.Contains(secError.Error(), "tls: oversized record received"),
		strings.Contains(secError.Error(), "server gave HTTP response to HTTPS"):
		r.Debug("DP1015", "docker-registry not secured; falling back to cleartext connection")
		if nosecError := processRegistryRequest(&noSecClient, fmt.Sprintf("http://%s:%s/v2/", registryHostname, registryPort), token, r); nosecError != nil {
			r.Error("DP1013", nosecError, fmt.Sprintf("Unexpected error authenticating to the integrated registry:\n(%T) %[1]v", nosecError))
		}
	default:
		r.Error("DP1013", secError, fmt.Sprintf("Unexpected error authenticating to the integrated registry:\n(%T) %[1]v", secError))
	}
}
Beispiel #18
0
/*
 * makeMessage() - construct DNS message structure
 */
func makeMessage(c *Context, qname, qtype, qclass string, ext Extension) *dns.Msg {

	m := new(dns.Msg)
	m.Id = dns.Id()

	if c.restype == RESOLUTION_STUB {
		m.RecursionDesired = true
	} else {
		m.RecursionDesired = false
	}

	if c.adflag {
		m.AuthenticatedData = true
	}

	if c.cdflag {
		m.CheckingDisabled = true
	}

	if ext["dnssec_return_status"] || ext["dnssec_return_only_secure"] || ext["dnssec_return_validation_chain"] {
		opt := new(dns.OPT)
		opt.Hdr.Name = "."
		opt.Hdr.Rrtype = dns.TypeOPT
		opt.SetDo()
		m.Extra = append(m.Extra, opt)
	}

	m.Question = make([]dns.Question, 1)
	qtype_int, ok := dns.StringToType[strings.ToUpper(qtype)]
	if !ok {
		fmt.Printf("%s: Unrecognized query type.\n", qtype)
		return nil
	}
	qclass_int, ok := dns.StringToClass[strings.ToUpper(qclass)]
	if !ok {
		fmt.Printf("%s: Unrecognized query class.\n", qclass)
		return nil
	}
	m.Question[0] = dns.Question{qname, qtype_int, qclass_int}

	return m
}
Beispiel #19
0
func (d *DnsDomain) Test() bool {
	if !(*Domain)(d).Test() {
		return false
	}

	fqdn := d.Name
	if strings.HasPrefix(fqdn, "*.") {
		fqdn = "a" + fqdn[1:]
	}
	if !strings.HasSuffix(fqdn, ".") {
		fqdn = fqdn + "."
	}

	any_ok := false

	d.DNS = make([]*DnsRecords, 0, len(DNS_servers))
	for name, addr := range DNS_servers {
		records := new(DnsRecords)
		records.Server = name
		records.NS = addr
		d.DNS = append(d.DNS, records)

		req := new(dns.Msg)
		req.Id = dns.Id()
		req.RecursionDesired = true
		req.Question = []dns.Question{
			dns.Question{fqdn, dns.TypeA, dns.ClassINET},
		}

		resp, err := dns_client.Exchange(req, addr)
		if err != nil {
			records.Status = 900
			records.Message = err.Error()
			continue
		}

		records.IPs = make([]string, 0, len(resp.Answer))
		for _, rr := range resp.Answer {
			switch a := rr.(type) {
			case *dns.RR_A:
				records.IPs = append(records.IPs, a.A.String())
			}
		}

		if len(records.IPs) > 0 {
			any_ok = true
		} else {
			records.Status = 900
			records.Message = "No records"
		}
	}

	return any_ok
}
Beispiel #20
0
func DnsGetDoaminIP(domain string) (string, error) {
	m := new(dns.Msg)
	m.Id = dns.Id()
	m.SetQuestion(dns.Fqdn(domain), dns.TypeA)
	m.RecursionDesired = true
	res, err := dnsQuery(m)
	if nil != err {
		return "", err
	}
	return pickIP(res), nil
}
Beispiel #21
0
func pinguer(domain string) (int, int) {

	// Every N steps, we will tell the stats module how many requests we sent
	maxRequestID := big.NewInt(65536)
	errors := 0
	totalSent := 0

	questionRecord := dns.TypeA

	message := new(dns.Msg).SetQuestion(domain, questionRecord)
	if iterative {
		message.RecursionDesired = false
	}

	for reqnumber := 0; count == 0 || reqnumber < count; reqnumber++ {

		// Try to resolve the domain
		if randomIds {
			// Regenerate message Id to avoid servers dropping (seemingly) duplicate messages
			newid, _ := rand.Int(rand.Reader, maxRequestID)
			message.Id = uint16(newid.Int64())
		}

		start := time.Now()
		err := dnsExchange(resolver, message)
		elapsedMilliSeconds := float64(time.Since(start)) / float64(time.Millisecond)

		if err != nil {
			if verbose {
				fmt.Printf("%s error: % (%s)\n", domain, err, resolver)
			}
			errors++
		}

		totalSent++

		// Display results of the ping
		fmt.Printf(
			"ping %s with %s %s: %.3fms\n",
			resolver,
			dns.TypeToString[questionRecord],
			domain,
			elapsedMilliSeconds,
		)

		time.Sleep(time.Duration(pingInterval) * time.Millisecond)
	}

	return totalSent, errors
}
Beispiel #22
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
}
func (resolver ConsulDnsAddressResolver) Resolve(service string) (string, error) {
	m1 := new(dns.Msg)
	m1.Id = dns.Id()
	m1.RecursionDesired = true
	m1.SetQuestion(service+".service.consul.", dns.TypeA)
	c := new(dns.Client)
	in, _, err := c.Exchange(m1, resolver.ServerAddress)
	if err != nil {
		log.Fatal(err)
	}
	if len(in.Answer) > 0 {
		log.Println(in.Answer)
		return in.Answer[0].(*dns.A).A.String(), nil
	}
	return "", errors.New("Could not resolve service address")
}
Beispiel #24
0
// ExampleRetrieverFunc uses a specific resolver with custom timeouts.
func ExampleRetrieverFunc() {
	discovery := dnsdisco.NewDiscovery("jabber", "tcp", "registro.br")
	discovery.SetRetriever(dnsdisco.RetrieverFunc(func(service, proto, name string) (servers []*net.SRV, err error) {
		client := dns.Client{
			ReadTimeout:  2 * time.Second,
			WriteTimeout: 2 * time.Second,
		}

		name = strings.TrimRight(name, ".")
		z := fmt.Sprintf("_%s._%s.%s.", service, proto, name)

		var request dns.Msg
		request.SetQuestion(z, dns.TypeSRV)
		request.RecursionDesired = true

		response, _, err := client.Exchange(&request, "8.8.8.8:53")
		if err != nil {
			return nil, err
		}

		for _, rr := range response.Answer {
			if srv, ok := rr.(*dns.SRV); ok {
				servers = append(servers, &net.SRV{
					Target:   srv.Target,
					Port:     srv.Port,
					Priority: srv.Priority,
					Weight:   srv.Weight,
				})
			}
		}

		return
	}))

	// Retrieve the servers
	if err := discovery.Refresh(); err != nil {
		fmt.Println(err)
		return
	}

	target, port := discovery.Choose()
	fmt.Printf("Target: %s\nPort: %d\n", target, port)

	// Output:
	// Target: jabber.registro.br.
	// Port: 5269
}
func findSoaNs(domain string) (string, string, string) {

	var cname string
	var soa string
	var ns string

	add := func(c, s, n string) {
		cname += c
		soa += s
		ns += n
		return
	}

	cname += domain + ","
	m1 := new(dns.Msg)
	m1.Id = dns.Id()
	m1.RecursionDesired = true
	m1.Question = make([]dns.Question, 1)
	m1.Question[0] = dns.Question{domain, dns.TypeSOA, dns.ClassINET}
	in, _ := dns.Exchange(m1, (cf.Servers[1] + ":53"))
	rrList := [...][]dns.RR{in.Answer, in.Ns, in.Extra}

	for _, rr := range rrList {
		for i := len(rr) - 1; i >= 0; i-- {
			switch rr[i].Header().Rrtype {
			case dns.TypeCNAME:
				temp_cname := rr[i].(*dns.CNAME)
				add(findSoaNs(temp_cname.Target))
				//				fmt.Println(  "temp_cname:" , temp_cname )
				return cname, soa, ns
				break
			case dns.TypeNS:
				temp_ns := rr[i].(*dns.NS)
				ns += temp_ns.Ns + "," // + "|" +  fmt.Sprint( temp_ns.Hdr.Ttl ) + ","
				//				fmt.Println(  "temp_ns:" , temp_ns )
				break
			case dns.TypeSOA:
				temp_soa := rr[i].(*dns.SOA)
				soa += temp_soa.Ns + "," // + "|" + fmt.Sprint( temp_soa.Hdr.Ttl ) + ","
				//				fmt.Println( "temp_soa:" , temp_soa )
				break
			}
		}
	}

	return cname, soa, ns
}
// dnsQuery sends a DNS query to the given nameserver.
// The nameserver should include a port, to facilitate testing where we talk to a mock dns server.
func dnsQuery(fqdn string, rtype uint16, nameserver string, recursive bool) (in *dns.Msg, err error) {
	m := new(dns.Msg)
	m.SetQuestion(fqdn, rtype)
	m.SetEdns0(4096, false)

	if !recursive {
		m.RecursionDesired = false
	}

	in, err = dns.Exchange(m, nameserver)
	if err == dns.ErrTruncated {
		tcp := &dns.Client{Net: "tcp"}
		in, _, err = tcp.Exchange(m, nameserver)
	}

	return
}
Beispiel #27
0
func (this *UDPNameServer) BuildQueryA(domain string, id uint16) *alloc.Buffer {
	buffer := alloc.NewBuffer()
	msg := new(dns.Msg)
	msg.Id = id
	msg.RecursionDesired = true
	msg.Question = []dns.Question{
		dns.Question{
			Name:   dns.Fqdn(domain),
			Qtype:  dns.TypeA,
			Qclass: dns.ClassINET,
		}}

	writtenBuffer, _ := msg.PackBuffer(buffer.Value)
	buffer.Slice(0, len(writtenBuffer))

	return buffer
}
Beispiel #28
0
func fakeMsg(dom string, rrHeader uint16, proto string, serverPort int) (*dns.Msg, error) {
	qc := uint16(dns.ClassINET)

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

	m := new(dns.Msg)
	m.Question = make([]dns.Question, 1)
	m.Question[0] = dns.Question{
		Name:   dns.Fqdn(dom),
		Qtype:  rrHeader,
		Qclass: qc,
	}
	m.RecursionDesired = true
	in, _, err := c.Exchange(m, "127.0.0.1:"+strconv.Itoa(serverPort))
	return in, err

}
Beispiel #29
0
// Lookup the IP address using HypeDNS
func lookupHypeDNS(hostname string) (response string, err error) {
	c := new(dns.Client)

	m := new(dns.Msg)
	m.SetQuestion(dns.Fqdn(hostname), dns.TypeAAAA)
	m.RecursionDesired = true

	r, _, err := c.Exchange(m, "[fc5d:baa5:61fc:6ffd:9554:67f0:e290:7535]:53")
	if r == nil || err != nil {
		return
	}

	// Stuff must be in the answer section
	for _, a := range r.Answer {
		columns := strings.Fields(a.String()) //column 4 holds the ip address
		return padIPv6(net.ParseIP(columns[4])), nil
	}
	return
}
Beispiel #30
0
func linearResolver(threadID int, domain string, sentCounterCh chan<- result) {
	// Resolve the domain as fast as possible
	if verbose {
		fmt.Printf("Starting thread #%d.\n", threadID)
	}

	// Every N steps, we will tell the stats module how many requests we sent
	displayStep := 5
	maxRequestID := big.NewInt(65536)
	errors := 0

	message := new(dns.Msg).SetQuestion(domain, dns.TypeA)
	if iterative {
		message.RecursionDesired = false
	}

	for {
		for i := 0; i < displayStep; i++ {
			// Try to resolve the domain
			if randomIds {
				// Regenerate message Id to avoid servers dropping (seemingly) duplicate messages
				newid, _ := rand.Int(rand.Reader, maxRequestID)
				message.Id = uint16(newid.Int64())
			}

			if flood {
				go dnsExchange(resolver, message)
			} else {
				err := dnsExchange(resolver, message)
				if err != nil {
					if verbose {
						fmt.Printf("%s error: % (%s)\n", domain, err, resolver)
					}
					errors++
				}
			}
		}

		// Update the counter of sent requests and requests
		sentCounterCh <- result{displayStep, errors}
		errors = 0
	}
}