Пример #1
0
func multidns(query *dns.Msg, out chan *dns.Msg) {
	start := time.Now()
	response := make(chan dnsresponse, len(servers))
	for _, server := range servers {
		go singlequery(query, server, response)
		//var req dnsrequest
		//req.query.response = query
		//req.query.server = server
		//req.channel = response
		//service <- req
	}

	var logline string
	sent := false
	var allresults []*dns.Msg
	for i := 0; i < len(servers); i++ {
		result := <-response
		if !sent && result.response != nil {
			//We have a winner...
			//Send only one response. query is satisfied. now dick around to collect more stats
			out <- result.response
			sent = true
			//Log with special flag. May not always be the first to answer...
			logline += fmt.Sprintf("%s (%s - W) ; ", result.server, time.Since(start))
		} else {
			//... but log everyone
			logline += fmt.Sprintf("%s (%s) ; ", result.server, time.Since(start))
		}
		//extract ips from result.response
		if result.response != nil {
			if iscachable(result.response) {
				for _, ans := range result.response.Answer {
					if ans.Header().Rrtype == dns.TypeA {
						//fmt.Printf("%s\n", ans.(*dns.A).A)
						ipchan <- fmt.Sprintf("%s", ans.(*dns.A).A)
					}
				}
				allresults = append(allresults, result.response)
			}
		}
	}
	//logline += "\n"
	var name []string
	for _, q := range query.Question {
		name = append(name, q.Name+":"+dns.Class(q.Qclass).String())
	}
	fmt.Printf("%s (%s): %s\n", start, name, logline)
	if len(allresults) > 0 {
		putincache(allresults)
	}
	//fmt.Printf("Exiting...\n")
}
Пример #2
0
// ServeDNS is the entry point for every request to the address that s
// is bound to. It acts as a multiplexer for the requests zonename as
// defined in the request so that the correct zone
// (configuration and middleware stack) will handle the request.
func (s *Server) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
	defer func() {
		// In case the user doesn't enable error middleware, we still
		// need to make sure that we stay alive up here
		if rec := recover(); rec != nil {
			DefaultErrorFunc(w, r, dns.RcodeServerFailure)
		}
	}()

	if m, err := middleware.Edns0Version(r); err != nil { // Wrong EDNS version, return at once.
		rc := middleware.RcodeToString(dns.RcodeBadVers)
		state := middleware.State{W: w, Req: r}

		metrics.Report(state, metrics.Dropped, rc, m.Len(), time.Now())
		w.WriteMsg(m)
		return
	}

	// Execute the optional request callback if it exists
	if s.ReqCallback != nil && s.ReqCallback(w, r) {
		return
	}

	q := r.Question[0].Name
	b := make([]byte, len(q))
	off, end := 0, false
	ctx := context.Background()

	for {
		l := len(q[off:])
		for i := 0; i < l; i++ {
			b[i] = q[off+i]
			// normalize the name for the lookup
			if b[i] >= 'A' && b[i] <= 'Z' {
				b[i] |= ('a' - 'A')
			}
		}

		if h, ok := s.zones[string(b[:l])]; ok {
			if r.Question[0].Qtype != dns.TypeDS {
				rcode, _ := h.stack.ServeDNS(ctx, w, r)
				if RcodeNoClientWrite(rcode) {
					DefaultErrorFunc(w, r, rcode)
				}
				return
			}
		}
		off, end = dns.NextLabel(q, off)
		if end {
			break
		}
	}
	// Wildcard match, if we have found nothing try the root zone as a last resort.
	if h, ok := s.zones["."]; ok {
		rcode, _ := h.stack.ServeDNS(ctx, w, r)
		if RcodeNoClientWrite(rcode) {
			DefaultErrorFunc(w, r, rcode)
		}
		return
	}

	// Still here? Error out with REFUSED and some logging
	remoteHost := w.RemoteAddr().String()
	DefaultErrorFunc(w, r, dns.RcodeRefused)
	log.Printf("[INFO] \"%s %s %s\" - No such zone at %s (Remote: %s)", dns.Type(r.Question[0].Qtype), dns.Class(r.Question[0].Qclass), q, s.Addr, remoteHost)
}
Пример #3
0
// Class returns the class of the question in the request.
func (s *State) Class() string { return dns.Class(s.Req.Question[0].Qclass).String() }
Пример #4
0
func questionToString(q dns.Question) string {
	return fmt.Sprintf("%s %s %s", q.Name, dns.Class(q.Qclass), dns.Type(q.Qtype))
}
Пример #5
0
func textConvertMessage(m *Message, s *bytes.Buffer) {
	isQuery := false
	printQueryAddress := false

	switch *m.Type {
	case Message_CLIENT_QUERY,
		Message_RESOLVER_QUERY,
		Message_AUTH_QUERY,
		Message_FORWARDER_QUERY,
		Message_TOOL_QUERY:
		isQuery = true
	case Message_CLIENT_RESPONSE,
		Message_RESOLVER_RESPONSE,
		Message_AUTH_RESPONSE,
		Message_FORWARDER_RESPONSE,
		Message_TOOL_RESPONSE:
		isQuery = false
	default:
		s.WriteString("[unhandled Message.Type]\n")
		return
	}

	if isQuery {
		textConvertTime(s, m.QueryTimeSec, m.QueryTimeNsec)
	} else {
		textConvertTime(s, m.ResponseTimeSec, m.ResponseTimeNsec)
	}
	s.WriteString(" ")

	switch *m.Type {
	case Message_CLIENT_QUERY,
		Message_CLIENT_RESPONSE:
		{
			s.WriteString("C")
		}
	case Message_RESOLVER_QUERY,
		Message_RESOLVER_RESPONSE:
		{
			s.WriteString("R")
		}
	case Message_AUTH_QUERY,
		Message_AUTH_RESPONSE:
		{
			s.WriteString("A")
		}
	case Message_FORWARDER_QUERY,
		Message_FORWARDER_RESPONSE:
		{
			s.WriteString("F")
		}
	case Message_STUB_QUERY,
		Message_STUB_RESPONSE:
		{
			s.WriteString("S")
		}
	case Message_TOOL_QUERY,
		Message_TOOL_RESPONSE:
		{
			s.WriteString("T")
		}
	}

	if isQuery {
		s.WriteString("Q ")
	} else {
		s.WriteString("R ")
	}

	switch *m.Type {
	case Message_CLIENT_QUERY,
		Message_CLIENT_RESPONSE,
		Message_AUTH_QUERY,
		Message_AUTH_RESPONSE:
		printQueryAddress = true
	}

	if printQueryAddress {
		textConvertIP(s, m.QueryAddress)
	} else {
		textConvertIP(s, m.ResponseAddress)
	}
	s.WriteString(" ")

	if m.SocketProtocol != nil {
		s.WriteString(m.SocketProtocol.String())
	}
	s.WriteString(" ")

	var err error
	msg := new(dns.Msg)
	if isQuery {
		s.WriteString(strconv.Itoa(len(m.QueryMessage)))
		s.WriteString("b ")
		err = msg.Unpack(m.QueryMessage)
	} else {
		s.WriteString(strconv.Itoa(len(m.ResponseMessage)))
		s.WriteString("b ")
		err = msg.Unpack(m.ResponseMessage)
	}

	if err != nil {
		s.WriteString("X ")
	} else {
		s.WriteString("\"" + msg.Question[0].Name + "\" ")
		s.WriteString(dns.Class(msg.Question[0].Qclass).String() + " ")
		s.WriteString(dns.Type(msg.Question[0].Qtype).String())
	}

	s.WriteString("\n")
}