Ejemplo n.º 1
0
// handleQUery is used to handle DNS queries in the configured domain
func (d *DNSServer) handleQuery(resp dns.ResponseWriter, req *dns.Msg) {
	q := req.Question[0]
	defer func(s time.Time) {
		d.logger.Printf("[DEBUG] dns: request for %v (%v)", q, time.Now().Sub(s))
	}(time.Now())

	// Switch to TCP if the client is
	network := "udp"
	if _, ok := resp.RemoteAddr().(*net.TCPAddr); ok {
		network = "tcp"
	}

	// Setup the message response
	m := new(dns.Msg)
	m.SetReply(req)
	m.Authoritative = true
	m.RecursionAvailable = (len(d.recursors) > 0)

	// Only add the SOA if requested
	if req.Question[0].Qtype == dns.TypeSOA {
		d.addSOA(d.domain, m)
	}

	// Dispatch the correct handler
	d.dispatch(network, req, m)

	// Write out the complete response
	if err := resp.WriteMsg(m); err != nil {
		d.logger.Printf("[WARN] dns: failed to respond: %v", err)
	}
}
Ejemplo n.º 2
0
// handlePtr is used to handle "reverse" DNS queries
func (d *DNSServer) handlePtr(resp dns.ResponseWriter, req *dns.Msg) {
	q := req.Question[0]
	defer func(s time.Time) {
		d.logger.Printf("[DEBUG] dns: request for %v (%v) from client %s (%s)",
			q, time.Now().Sub(s), resp.RemoteAddr().String(),
			resp.RemoteAddr().Network())
	}(time.Now())

	// Setup the message response
	m := new(dns.Msg)
	m.SetReply(req)
	m.Authoritative = true
	m.RecursionAvailable = (len(d.recursors) > 0)

	// Only add the SOA if requested
	if req.Question[0].Qtype == dns.TypeSOA {
		d.addSOA(d.domain, m)
	}

	datacenter := d.agent.config.Datacenter

	// Get the QName without the domain suffix
	qName := strings.ToLower(dns.Fqdn(req.Question[0].Name))

	args := structs.DCSpecificRequest{
		Datacenter: datacenter,
		QueryOptions: structs.QueryOptions{
			Token:      d.agent.config.ACLToken,
			AllowStale: d.config.AllowStale,
		},
	}
	var out structs.IndexedNodes

	// TODO: Replace ListNodes with an internal RPC that can do the filter
	// server side to avoid transferring the entire node list.
	if err := d.agent.RPC("Catalog.ListNodes", &args, &out); err == nil {
		for _, n := range out.Nodes {
			arpa, _ := dns.ReverseAddr(n.Address)
			if arpa == qName {
				ptr := &dns.PTR{
					Hdr: dns.RR_Header{Name: q.Name, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: 0},
					Ptr: fmt.Sprintf("%s.node.%s.%s", n.Node, datacenter, d.domain),
				}
				m.Answer = append(m.Answer, ptr)
				break
			}
		}
	}

	// nothing found locally, recurse
	if len(m.Answer) == 0 {
		d.handleRecurse(resp, req)
		return
	}

	// Write out the complete response
	if err := resp.WriteMsg(m); err != nil {
		d.logger.Printf("[WARN] dns: failed to respond: %v", err)
	}
}
Ejemplo n.º 3
0
// ServeDNS resolution.
func (h *RandomUpstream) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
	ns := h.upstream[rand.Intn(len(h.upstream))]
	ns = defaultPort(ns)

	for _, q := range r.Question {
		log.Printf("[info] [%v] <== %s %s %v (ns %s)\n", r.Id,
			dns.ClassToString[q.Qclass],
			dns.TypeToString[q.Qtype],
			q.Name,
			ns)
	}

	client := &dns.Client{
		Net: w.RemoteAddr().Network(),
	}

	res, rtt, err := client.Exchange(r, ns)
	if err != nil {
		msg := new(dns.Msg)
		msg.SetRcode(r, dns.RcodeServerFailure)
		w.WriteMsg(msg)
		return
	}

	log.Printf("[info] [%v] ==> %s:", r.Id, rtt)
	for _, a := range res.Answer {
		log.Printf("[info] [%v] ----> %s\n", r.Id, a)
	}

	err = w.WriteMsg(res)
	if err != nil {
		log.Printf("[error] [%v] failed to respond – %s", r.Id, err)
	}
}
Ejemplo n.º 4
0
func (self *TrivialDnsServer) redirectQuery(w dns.ResponseWriter, r *dns.Msg, newName string) {
	self.Count("redirected_requests")
	if !strings.HasSuffix(newName, ".") {
		newName = newName + "."
	}

	newR := new(dns.Msg)
	newR.SetQuestion(dns.Fqdn(newName), dns.TypeA)

	if response, _, err := self.exchangeWithUpstream(newR); err == nil {
		ip := self.getSingleSimpleAnswer(response)
		if ip == nil {
			debug("%s redirect to %s yielded no answer", w.RemoteAddr(), newName)
			self.Count("redirected_nowhere")
			self.refuse(w, r)
			return
		}
		self.Count("redirected_successively")
		self.respondSuccessively(w, r, *ip)
	} else {
		self.Count("upstream_errors")
		self.refuse(w, r)
		log.Printf("%s: error: %s", w.RemoteAddr(), err)
	}
}
Ejemplo n.º 5
0
func (h ENUMHandler) ServeDNS(writer dns.ResponseWriter, request *dns.Msg) {

	defer func(s time.Time) {
		h.Trace.Printf("dns request for %v (%s) (%v) from client %s (%s)",
			request.Question[0], "udp", time.Now().Sub(s), writer.RemoteAddr().String(),
			writer.RemoteAddr().Network())
	}(time.Now())

	if answer, err := h.createAnswer(request); err == nil {

		if answer == nil {
			h.Trace.Printf("no result found for %s", request.Question[0])
			notfound := &dns.Msg{}
			notfound.SetReply(request)
			notfound.SetRcode(request, dns.RcodeSuccess)
			writer.WriteMsg(notfound)
			return
		}

		if err := writer.WriteMsg(answer); err != nil {
			h.Error.Printf("error sending answer: %v", err)
		}

	} else {
		h.Error.Printf("[ERR] Error getting the answer: %v", err)
		error := &dns.Msg{}
		error.SetReply(request)
		error.SetRcode(request, dns.RcodeServerFailure)
		writer.WriteMsg(error)
	}

}
Ejemplo n.º 6
0
func ( p Proxy ) ServeDNS (w dns.ResponseWriter, r *dns.Msg) {
    c := dns.NewClient ()

    c.Net = PROTO
    if TCP_REGEX != nil {
        for _, q := range r.Question {
            if TCP_REGEX.MatchString (q.Name) {
                LOG.Printf ("Tcp proto regex match: %s", q.Name)
                c.Net = "tcp"
                break
            }
        }
    }

    c.ReadTimeout = TIMEOUT
    c.WriteTimeout = TIMEOUT

    if rs, err := c.Exchange (r, p.Server()); err == nil {
        if DEBUG {
            LOG.Printf ("DEBUG %s\n%v", w.RemoteAddr(), rs)
        }
        w.Write (rs)
    } else {
        dns.Refused (w, r)
        LOG.Printf ("%s %s", w.RemoteAddr(), err)
    }
}
Ejemplo n.º 7
0
func proxy(addr string, w dns.ResponseWriter, req *dns.Msg) {
	transport := "udp"
	if _, ok := w.RemoteAddr().(*net.TCPAddr); ok {
		transport = "tcp"
	}
	if isTransfer(req) {
		if transport != "tcp" {
			dns.HandleFailed(w, req)
			return
		}
		t := new(dns.Transfer)
		c, err := t.In(req, addr)
		if err != nil {
			dns.HandleFailed(w, req)
			return
		}
		if err = t.Out(w, req, c); err != nil {
			dns.HandleFailed(w, req)
			return
		}
		return
	}
	c := &dns.Client{Net: transport}
	resp, _, err := c.Exchange(req, addr)
	if err != nil {
		dns.HandleFailed(w, req)
		return
	}
	w.WriteMsg(resp)
}
Ejemplo n.º 8
0
// handleRecurse is used to handle recursive DNS queries
func (d *DNSServer) handleRecurse(resp dns.ResponseWriter, req *dns.Msg) {
	q := req.Question[0]
	network := "udp"
	defer func(s time.Time) {
		d.logger.Printf("[DEBUG] dns: request for %v (%s) (%v)", q, network, time.Now().Sub(s))
	}(time.Now())

	// Switch to TCP if the client is
	if _, ok := resp.RemoteAddr().(*net.TCPAddr); ok {
		network = "tcp"
	}

	// Recursively resolve
	c := &dns.Client{Net: network}
	r, rtt, err := c.Exchange(req, d.recursor)

	// On failure, return a SERVFAIL message
	if err != nil {
		d.logger.Printf("[ERR] dns: recurse failed: %v", err)
		m := &dns.Msg{}
		m.SetReply(req)
		m.RecursionAvailable = true
		m.SetRcode(req, dns.RcodeServerFailure)
		resp.WriteMsg(m)
		return
	}
	d.logger.Printf("[DEBUG] dns: recurse RTT for %v (%v)", q, rtt)

	// Forward the response
	if err := resp.WriteMsg(r); err != nil {
		d.logger.Printf("[WARN] dns: failed to respond: %v", err)
	}
}
Ejemplo n.º 9
0
func (s *DNS) handleDNSExternal(w dns.ResponseWriter, req *dns.Msg) {

	network := "udp"
	if _, ok := w.RemoteAddr().(*net.TCPAddr); ok {
		network = "tcp"
	}

	c := &dns.Client{Net: network}
	var r *dns.Msg
	var err error
	for _, recursor := range s.recursors {

		if recursor == "" {
			log.Printf("Found empty recursor")
			continue
		}

		log.Printf("Forwarding request to external recursor for: %s", req.Question[0].Name)

		r, _, err = c.Exchange(req, recursor)
		if err == nil {
			if err := w.WriteMsg(r); err != nil {
				log.Printf("DNS lookup failed %v", err)
			}
			return
		}
	}

	dns.HandleFailed(w, req)
}
Ejemplo n.º 10
0
// Forwards a DNS request to the specified nameservers. On success, the
// original reply packet will be returned to the caller. On failure, a
// new packet will be returned with `RCODE` set to `SERVFAIL`.
// Even though the original `ResponseWriter` object is taken as an argument,
// this function does not send a reply to the client. Instead, the
// packet is returned for further processing by the caller.
func getServerReply(w dns.ResponseWriter, req *dns.Msg) *dns.Msg {
	if *verbose {
		log.Print("Forwarding ", req.Question[0].Name, "/", dns.Type(req.Question[0].Qtype).String())
	}

	// create a new DNS client

	client := &dns.Client{Net: "udp", ReadTimeout: 4 * time.Second, WriteTimeout: 4 * time.Second, SingleInflight: true}

	if _, tcp := w.RemoteAddr().(*net.TCPAddr); tcp {
		client.Net = "tcp"
	}

	var r *dns.Msg
	var err error

	// loop through the specified nameservers and forward them the request

	// the request ID is used as a starting point in order to introduce at least
	// some element of randomness, instead of always hitting the first nameserver

	for i := 0; i < len(nameservers); i++ {
		r, _, err = client.Exchange(req, nameservers[(int(req.Id)+i)%len(nameservers)])

		if err == nil {
			r.Compress = true

			return r
		}
	}

	log.Print("Failed to forward request.", err)
	return getEmptyMsg(w, req, dns.RcodeServerFailure)
}
Ejemplo n.º 11
0
func (h *Handler) handle(proto string, w dns.ResponseWriter, r *dns.Msg) {
	ques := question.NewQuestion(r.Question[0])

	subnet := ""
	if ip, ok := w.RemoteAddr().(*net.UDPAddr); ok {
		subnet = networks.Find(ip.IP)
	}
	if ip, ok := w.RemoteAddr().(*net.TCPAddr); ok {
		subnet = networks.Find(ip.IP)
	}

	if subnet == "" {
		dns.HandleFailed(w, r)
		return
	}

	if ques.IsIpQuery && ques.TopDomain == "vpn" {
		msg, err := h.reslvr.LookupUser(proto, ques, subnet, r)
		if err != nil {
			dns.HandleFailed(w, r)
			return
		}
		w.WriteMsg(msg)
	} else {
		servers := database.DnsServers[subnet]
		res, err := h.reslvr.Lookup(proto, servers, r)
		if err != nil {
			dns.HandleFailed(w, r)
			return
		}

		w.WriteMsg(res)
	}
}
Ejemplo n.º 12
0
// Proto gets the protocol used as the transport. This will be udp or tcp.
func Proto(w dns.ResponseWriter) string {
	if _, ok := w.RemoteAddr().(*net.UDPAddr); ok {
		return "udp"
	}
	if _, ok := w.RemoteAddr().(*net.TCPAddr); ok {
		return "tcp"
	}
	return "udp"
}
Ejemplo n.º 13
0
func handleRequest(w dns.ResponseWriter, r *dns.Msg) {
	kv := llog.KV{}
	// Can be nil during testing
	if raddr := w.RemoteAddr(); raddr != nil {
		kv["srcAddr"] = raddr.String()
	}

	if err := validateRequest(r); err != nil {
		kv["err"] = err
		llog.Warn("invalid request", kv)
		sendFormatError(w, r)
		return
	}

	start := time.Now()
	kv["question"] = r.Question[0].Name
	kv["questionType"] = r.Question[0].Qtype
	llog.Info("handling request", kv)

	rr := NewReq{r, make(chan *dns.Msg)}
	newCh <- rr
	m := <-rr.ReplyCh

	kv["ms"] = int64(time.Since(start).Nanoseconds() / 1e6)

	if m == nil {
		llog.Warn("error handling request", kv)
		dns.HandleFailed(w, r)
		return
	}

	//we need to make sure the sent ID matches the replied one
	//it might be different if we combined in-flight messages
	//copy the struct so we don't affect anything else handling this
	m2 := *m
	m2.Id = r.Id
	m = &m2

	//we always want to compress since there's no downsides afaik
	m.Compress = true

	kv["rcode"], _ = dns.RcodeToString[m.Rcode]
	if len(m.Answer) > 0 {
		kv["answer"] = m.Answer[0]
		kv["answerCnt"] = len(m.Answer)
	}
	kv["len"] = m.Len()
	llog.Info("responding to request", kv)

	err := w.WriteMsg(m)
	if err != nil {
		kv["err"] = err
		llog.Warn("error writing response", kv)
		//no need to handle HandleFailed here because we cannot write
	}
}
Ejemplo n.º 14
0
func (ds *DNSServer) ServeDNS(rw dns.ResponseWriter, mes *dns.Msg) {
	resp := new(dns.Msg)

	for _, q := range mes.Question {
		log.Printf("DNS request from %s: %s", rw.RemoteAddr(), &q)
		switch q.Qtype {
		case dns.TypeA, dns.TypeAAAA:
			val, err := ds.HandleLookup(q.Name)
			if err != nil {
				log.Println(err)
				continue
			}

			if q.Qclass != dns.ClassINET {
				log.Printf("error: got invalid DNS question class %d\n", q.Qclass)
				continue
			}

			header := dns.RR_Header{
				Name:   q.Name,
				Rrtype: q.Qtype,
				Class:  dns.ClassINET,
				Ttl:    DefaultResponseTTL,
			}

			var rr dns.RR
			// not really super sure why these have to be different types
			if q.Qtype == dns.TypeA {
				rr = &dns.A{
					A:   net.ParseIP(val),
					Hdr: header,
				}
			} else if q.Qtype == dns.TypeAAAA {
				rr = &dns.AAAA{
					AAAA: net.ParseIP(val),
					Hdr:  header,
				}
			} else {
				panic("unreachable")
			}

			resp.Answer = append(resp.Answer, rr)

		default:
			log.Printf("unhandled qtype: %d\n", q.Qtype)
		}
	}

	resp.Authoritative = true
	resp.Id = mes.Id
	resp.Response = true

	if err := rw.WriteMsg(resp); err != nil {
		log.Printf("error responding to DNS query: %s", err)
	}
}
Ejemplo n.º 15
0
// HandleNonMesos handles non-mesos queries by forwarding to configured
// external DNS servers.
func (res *Resolver) HandleNonMesos(w dns.ResponseWriter, r *dns.Msg) {
	logging.CurLog.NonMesosRequests.Inc()
	m, err := res.fwd(r, w.RemoteAddr().Network())
	if err != nil {
		m = new(dns.Msg).SetRcode(r, rcode(err))
	} else if len(m.Answer) == 0 {
		logging.CurLog.NonMesosNXDomain.Inc()
	}
	reply(w, m)
}
Ejemplo n.º 16
0
func sendTruncated(w dns.ResponseWriter, msgHdr dns.MsgHdr) {
	emptyResp := new(dns.Msg)
	emptyResp.MsgHdr = msgHdr
	emptyResp.Response = true
	if _, isTCP := w.RemoteAddr().(*net.TCPAddr); isTCP {
		dns.HandleFailed(w, emptyResp)
		return
	}
	emptyResp.Truncated = true
	w.WriteMsg(emptyResp)
}
Ejemplo n.º 17
0
func debug_request(request dns.Msg, question dns.Question, writer dns.ResponseWriter) string {
	addr := writer.RemoteAddr().String() // ipaddr string
	s := []string{}
	// TODO: put tcp/udp in here
	s = append(s, fmt.Sprintf("Received request from %s ", addr))
	s = append(s, fmt.Sprintf("for %s ", question.Name))
	s = append(s, fmt.Sprintf("opcode: %d ", request.Opcode))
	s = append(s, fmt.Sprintf("rrtype: %d ", question.Qtype))
	s = append(s, fmt.Sprintf("rrclass: %d ", question.Qclass))
	return strings.Join(s, "")
}
Ejemplo n.º 18
0
Archivo: dns.go Proyecto: kjplatz/vic
// HandleForwarding forwards a request to the nameservers and returns the response
func (s *Server) HandleForwarding(w mdns.ResponseWriter, r *mdns.Msg) (bool, error) {
	defer trace.End(trace.Begin(r.String()))

	var m *mdns.Msg
	var err error
	var try int

	if len(s.Nameservers) == 0 {
		log.Errorf("No nameservers defined, can not forward")
		return false, respServerFailure(w, r)
	}

	// which protocol are they talking
	tcp := false
	if _, ok := w.RemoteAddr().(*net.TCPAddr); ok {
		tcp = true
	}

	// Use request ID for "random" nameserver selection.
	nsid := int(r.Id) % len(s.Nameservers)

Redo:
	nameserver := s.Nameservers[nsid]
	if i := strings.Index(nameserver, ":"); i < 0 {
		nameserver += ":53"
	}

	if tcp {
		m, _, err = s.tcpclient.Exchange(r, nameserver)
	} else {
		m, _, err = s.udpclient.Exchange(r, nameserver)
	}
	if err != nil {
		// Seen an error, this can only mean, "server not reached", try again but only if we have not exausted our nameservers.
		if try < len(s.Nameservers) {
			try++
			nsid = (nsid + 1) % len(s.Nameservers)
			goto Redo
		}

		log.Errorf("Failure to forward request: %q", err)
		return false, respServerFailure(w, r)
	}

	// We have a response so cache it
	s.cache.Add(m)

	m.Compress = true
	if err := w.WriteMsg(m); err != nil {
		log.Errorf("Error writing response: %q", err)
		return true, err
	}
	return true, nil
}
Ejemplo n.º 19
0
func allowed(w dns.ResponseWriter, req *dns.Msg) bool {
	if !isTransfer(req) {
		return true
	}
	remote := extractHost(w.RemoteAddr().String())
	for _, ip := range transferIPs {
		if ip == remote {
			return true
		}
	}
	return false
}
Ejemplo n.º 20
0
func (z *zone) zoneHandler(c *config, w dns.ResponseWriter, req *dns.Msg) {
	c.stats.Incr("query.request", 1)
	m := new(dns.Msg)
	m.SetReply(req)
	m.Authoritative = true
	m.Answer = []dns.RR{}
	questions := []string{}
	answers := []string{}
	if len(req.Question) != 1 {
		c.stats.Incr("query.error", 1)
		log.Printf("Warning: len(req.Question) != 1")
		return
	}
	q := req.Question[0]
	questions = append(questions, fmt.Sprintf("%s[%s]", q.Name, dns.TypeToString[q.Qtype]))
	if q.Qclass != uint16(dns.ClassINET) {
		c.stats.Incr("query.error", 1)
		log.Printf("Warning: skipping unhandled class: %s", dns.ClassToString[q.Qclass])
		return
	}
	for _, record := range z.rrs {
		h := record.Header()
		if q.Name != h.Name {
			continue
		}
		txt := record.String()
		if q.Qtype == dns.TypeA && h.Rrtype == dns.TypeCNAME { // special handling for A queries w/CNAME results
			if q.Name == dns.Fqdn(z.name) { // flatten root CNAME
				flat, err := c.flattenCNAME(record.(*dns.CNAME))
				if err != nil || flat == nil {
					log.Printf("flattenCNAME error: %s", err.Error())
				} else {
					for _, record := range flat {
						m.Answer = append(m.Answer, record)
						answers = append(answers, "(FLAT)"+record.String())
					}
				}
				continue
			} // don't flatten other CNAMEs for now
		} else if q.Qtype != h.Rrtype && q.Qtype != dns.TypeANY { // skip RRs that don't match
			continue
		}
		m.Answer = append(m.Answer, record)
		answers = append(answers, txt)
	}
	//m.Extra = []dns.RR{}
	//m.Extra = append(m.Extra, &dns.TXT{Hdr: dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0}, Txt: []string{"DNS rocks"}})
	c.debug(fmt.Sprintf("Query [%s] %s -> %s ", w.RemoteAddr().String(), strings.Join(questions, ","), strings.Join(answers, ",")))
	c.stats.Incr("query.answer", 1)

	w.WriteMsg(m)
}
Ejemplo n.º 21
0
func (self *TrivialDnsServer) proxyToUpstream(w dns.ResponseWriter, r *dns.Msg) {
	self.Count("proxied_requests")
	if response, _, err := self.exchangeWithUpstream(r); err == nil {
		if len(response.Answer) == 0 {
			self.Count("proxied_refusals")
		}
		w.WriteMsg(response)
	} else {
		self.Count("upstream_errors")
		self.refuse(w, r)
		log.Printf("%s: error: %s", w.RemoteAddr(), err)
	}
}
Ejemplo n.º 22
0
func Handle(writer dns.ResponseWriter, request *dns.Msg) {
	question := request.Question[0]

	message := new(dns.Msg)
	message.SetReply(request)
	message.SetRcode(message, dns.RcodeSuccess)

	full_address := writer.RemoteAddr().String()
	address := strings.Split(full_address, ":")[0]

	if allowed(address) != true {
		msg := fmt.Sprintf("ERROR %s : %s not allowed to talk to slappy", question.Name, address)
		logger.Error(msg)
		message = handle_error(message, writer, "REFUSED")
		respond(message, question, *request, writer)
		return
	}

	logger.Debug(debug_request(*request, question, writer))

	go Stat("query")

	switch request.Opcode {
	case dns.OpcodeNotify:
		message = handle_notify(question, message, writer)
	case CC:
		if question.Qclass == ClassCC {
			switch question.Qtype {
			case CREATE:
				message = handle_create(question, message, writer)
			case DELETE:
				message = handle_delete(question, message, writer)
			default:
				message = handle_error(message, writer, "REFUSED")
			}
		} else {
			logger.Debug(fmt.Sprintf("ERROR %s : unsupported rrclass %d", question.Name, question.Qclass))
			message = handle_error(message, writer, "REFUSED")
		}
	default:
		if question.Name == conf.Stats_uri {
			message = Stats_dns_message(message, writer)
			logger.Debug("SUCCESS STATS : Sent runtime stats")
			break
		}
		logger.Debug(fmt.Sprintf("ERROR %s : unsupported opcode %d", question.Name, request.Opcode))
		message = handle_error(message, writer, "REFUSED")
	}

	respond(message, question, *request, writer)
}
Ejemplo n.º 23
0
// ServeDNSForward forwards a request to a nameservers and returns the response.
func (s *server) ServeDNSForward(w dns.ResponseWriter, req *dns.Msg) {
	StatsForwardCount.Inc(1)
	if len(s.config.Nameservers) == 0 || dns.CountLabel(req.Question[0].Name) < s.config.Ndots {
		s.config.log.Infof("no nameservers defined or name too short, can not forward")
		m := new(dns.Msg)
		m.SetReply(req)
		m.SetRcode(req, dns.RcodeServerFailure)
		m.Authoritative = false     // no matter what set to false
		m.RecursionAvailable = true // and this is still true
		w.WriteMsg(m)
		return
	}
	tcp := false
	if _, ok := w.RemoteAddr().(*net.TCPAddr); ok {
		tcp = true
	}

	var (
		r   *dns.Msg
		err error
		try int
	)
	// Use request Id for "random" nameserver selection.
	nsid := int(req.Id) % len(s.config.Nameservers)
Redo:
	switch tcp {
	case false:
		r, _, err = s.dnsUDPclient.Exchange(req, s.config.Nameservers[nsid])
	case true:
		r, _, err = s.dnsTCPclient.Exchange(req, s.config.Nameservers[nsid])
	}
	if err == nil {
		r.Compress = true
		w.WriteMsg(r)
		return
	}
	// Seen an error, this can only mean, "server not reached", try again
	// but only if we have not exausted our nameservers.
	if try < len(s.config.Nameservers) {
		try++
		nsid = (nsid + 1) % len(s.config.Nameservers)
		goto Redo
	}

	s.config.log.Errorf("failure to forward request %q", err)
	m := new(dns.Msg)
	m.SetReply(req)
	m.SetRcode(req, dns.RcodeServerFailure)
	w.WriteMsg(m)
}
Ejemplo n.º 24
0
// makes non-mesos queries to external nameserver
func (res *Resolver) HandleNonMesos(w dns.ResponseWriter, r *dns.Msg) {
	var err error
	var m *dns.Msg

	// tracing info
	logging.CurLog.NonMesosRequests.Inc()

	// If external request are disabled
	if !res.config.ExternalOn {
		m = new(dns.Msg)
		// set refused
		m.SetRcode(r, 5)
	} else {

		proto := "udp"
		if _, ok := w.RemoteAddr().(*net.TCPAddr); ok {
			proto = "tcp"
		}

		for _, resolver := range res.config.Resolvers {
			nameserver := net.JoinHostPort(resolver, "53")
			m, err = res.extResolver(r, nameserver, proto, recurseCnt)
			if err == nil {
				break
			}
		}
	}

	// extResolver returns nil Msg sometimes cause of perf
	if m == nil {
		m = new(dns.Msg)
		m.SetRcode(r, 2)
		err = errors.New("nil msg")
	}
	if err != nil {
		logging.Error.Println(r.Question[0].Name)
		logging.Error.Println(err)
		logging.CurLog.NonMesosFailed.Inc()
	} else {
		// nxdomain
		if len(m.Answer) == 0 {
			logging.CurLog.NonMesosNXDomain.Inc()
		} else {
			logging.CurLog.NonMesosSuccess.Inc()
		}
	}

	reply(w, m)
}
Ejemplo n.º 25
0
// ServeDNS is the handler for DNS requests, responsible for parsing DNS request, possibly forwarding
// it to a real dns server and returning a response.
func (s *Server) ServeDNS(w dns.ResponseWriter, req *dns.Msg) {
	stats.RequestCount.Inc(1)

	q := req.Question[0]
	log.Printf("Received DNS Request for %q from %q", q.Name, w.RemoteAddr())

	// If the query does not fall in our s.domain, forward it
	if !strings.HasSuffix(q.Name, dns.Fqdn(s.domain)) {
		s.ServeDNSForward(w, req)
		return
	}
	m := new(dns.Msg)
	m.SetReply(req)
	m.Authoritative = true
	m.RecursionAvailable = true
	m.Answer = make([]dns.RR, 0, 10)
	defer w.WriteMsg(m)

	if q.Qtype == dns.TypeANY || q.Qtype == dns.TypeSRV {
		records, extra, err := s.getSRVRecords(q)

		if err != nil {
			// We are authoritative for this name, but it does not exist: NXDOMAIN
			m.SetRcode(req, dns.RcodeNameError)
			m.Ns = s.createSOA()
			log.Println("Error: ", err)
			return
		}

		m.Answer = append(m.Answer, records...)
		m.Extra = append(m.Extra, extra...)
	}

	if q.Qtype == dns.TypeA || q.Qtype == dns.TypeAAAA {
		records, err := s.getARecords(q)

		if err != nil {
			m.SetRcode(req, dns.RcodeNameError)
			m.Ns = s.createSOA()
			log.Println("Error: ", err)
			return
		}
		m.Answer = append(m.Answer, records...)
	}
	if len(m.Answer) == 0 { // Send back a NODATA response
		m.Ns = s.createSOA()
	}
}
// 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)
	}
}
Ejemplo n.º 27
0
func (self *TrivialDnsServer) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
	defer func() {
		if err := recover(); err != nil {
			runtime_debug.PrintStack()
			log.Printf("PANIC: %s", err)
			self.refuseOnPanic(w, r)
		}
	}()

	log.Printf("INFO: QUERY, remote_addr=%v query=%v\n", w.RemoteAddr(), r.Question[0].Name)
	self.Count("requests")
	if self.tryAnswer(w, r) {
		return
	}
	self.proxyToUpstream(w, r)
}
Ejemplo n.º 28
0
// handleRecurse is used to handle recursive DNS queries
func (d *DNSServer) handleRecurse(resp dns.ResponseWriter, req *dns.Msg) {
	q := req.Question[0]
	network := "udp"
	defer func(s time.Time) {
		d.logger.Printf("[DEBUG] dns: request for %v (%s) (%v) from client %s (%s)",
			q, network, time.Now().Sub(s), resp.RemoteAddr().String(),
			resp.RemoteAddr().Network())
	}(time.Now())

	// Switch to TCP if the client is
	if _, ok := resp.RemoteAddr().(*net.TCPAddr); ok {
		network = "tcp"
	}

	// Recursively resolve
	c := &dns.Client{Net: network, Timeout: d.config.RecursorTimeout}
	var r *dns.Msg
	var rtt time.Duration
	var err error
	for _, recursor := range d.recursors {
		r, rtt, err = c.Exchange(req, recursor)
		if err == nil {
			// Compress the response; we don't know if the incoming
			// response was compressed or not, so by not compressing
			// we might generate an invalid packet on the way out.
			r.Compress = !d.config.DisableCompression

			// Forward the response
			d.logger.Printf("[DEBUG] dns: recurse RTT for %v (%v)", q, rtt)
			if err := resp.WriteMsg(r); err != nil {
				d.logger.Printf("[WARN] dns: failed to respond: %v", err)
			}
			return
		}
		d.logger.Printf("[ERR] dns: recurse failed: %v", err)
	}

	// If all resolvers fail, return a SERVFAIL message
	d.logger.Printf("[ERR] dns: all resolvers failed for %v from client %s (%s)",
		q, resp.RemoteAddr().String(), resp.RemoteAddr().Network())
	m := &dns.Msg{}
	m.SetReply(req)
	m.Compress = !d.config.DisableCompression
	m.RecursionAvailable = true
	m.SetRcode(req, dns.RcodeServerFailure)
	resp.WriteMsg(m)
}
Ejemplo n.º 29
0
func (t *UsageTracker) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
	var latest *usage.ProjectVersion
	var event *TrackingEvent

	m := new(dns.Msg)
	m.SetReply(r)

	q := r.Question[0].Name

	pv, err := usage.ParseV1(q)
	if err != nil {
		log.Printf("error parsing %s (%s): %s", q, w.RemoteAddr().(*net.UDPAddr).IP, err)
		// m.Rcode = dns.RcodeRefused
		m.Rcode = dns.RcodeNameError
		goto response
	}

	latest, err = t.GetLatest(pv)
	if err != nil {
		// TODO if format is right, but project is missing,
		// return an NXDOMAIN error
		log.Printf("error fetching latest for %v: %s", pv, err)
		m.Rcode = dns.RcodeNameError
		goto response
	}

	// do this after getting the version so we don't track results for
	// projects that aren't found
	event = &TrackingEvent{*pv, ""}
	if addr, ok := w.RemoteAddr().(*net.UDPAddr); ok {
		event.ClientAddress = addr.IP.String()
	}
	if err = t.Track(event); err != nil {
		log.Printf("error tracking %v: %s", event, err)
		// tracking error is not fatal, so still return the results
	}

	m.Answer = append(m.Answer, PtrRecord(latest))

response:
	err = w.WriteMsg(m)
	if err != nil {
		log.Printf("error writing response %v: %s", m, err)
	}
}
Ejemplo n.º 30
0
// ServeDNSForward forwards a request to a nameservers and returns the response.
func (s *server) ServeDNSForward(w dns.ResponseWriter, req *dns.Msg) {
	if len(s.config.Nameservers) == 0 {
		log.Printf("error: Failure to Forward DNS Request, no servers configured %q", dns.ErrServ)
		m := new(dns.Msg)
		m.SetReply(req)
		m.SetRcode(req, dns.RcodeServerFailure)
		m.Authoritative = false     // no matter what set to false
		m.RecursionAvailable = true // and this is still true
		w.WriteMsg(m)
		return
	}
	network := "udp"
	if _, ok := w.RemoteAddr().(*net.TCPAddr); ok {
		network = "tcp"
	}

	c := &dns.Client{Net: network, ReadTimeout: s.config.ReadTimeout}

	// Use request Id for "random" nameserver selection
	nsid := int(req.Id) % len(s.config.Nameservers)
	try := 0
Redo:
	r, _, err := c.Exchange(req, s.config.Nameservers[nsid])
	if err == nil {
		log.Printf("Forwarded DNS Request %q to %q", req.Question[0].Name, s.config.Nameservers[nsid])
		w.WriteMsg(r)
		return
	}
	// Seen an error, this can only mean, "server not reached", try again
	// but only if we have not exausted our nameservers
	if try < len(s.config.Nameservers) {
		log.Printf("error: Failure to Forward DNS Request %q to %q", err, s.config.Nameservers[nsid])
		try++
		nsid = (nsid + 1) % len(s.config.Nameservers)
		goto Redo
	}

	log.Printf("error: Failure to Forward DNS Request %q", err)
	m := new(dns.Msg)
	m.SetReply(req)
	m.SetRcode(req, dns.RcodeServerFailure)
	w.WriteMsg(m)
}