Beispiel #1
0
func (p ReverseProxy) ServeDNS(w dns.ResponseWriter, r *dns.Msg, extra []dns.RR) error {
	var (
		reply *dns.Msg
		err   error
	)

	switch {
	case middleware.Proto(w) == "tcp":
		reply, err = middleware.Exchange(p.Client.TCP, r, p.Host)
	default:
		reply, err = middleware.Exchange(p.Client.UDP, r, p.Host)
	}

	if reply != nil && reply.Truncated {
		// Suppress proxy error for truncated responses
		err = nil
	}

	if err != nil {
		return err
	}

	reply.Compress = true
	reply.Id = r.Id
	w.WriteMsg(reply)
	return nil
}
Beispiel #2
0
// shouldTransfer checks the primaries of zone, retrieves the SOA record, checks the current serial
// and the remote serial and will return true if the remote one is higher than the locally configured one.
func (z *Zone) shouldTransfer() (bool, error) {
	c := new(dns.Client)
	c.Net = "tcp" // do this query over TCP to minimize spoofing
	m := new(dns.Msg)
	m.SetQuestion(z.origin, dns.TypeSOA)

	var Err error
	serial := -1

Transfer:
	for _, tr := range z.TransferFrom {
		Err = nil
		ret, err := middleware.Exchange(c, m, tr)
		if err != nil || ret.Rcode != dns.RcodeSuccess {
			Err = err
			continue
		}
		for _, a := range ret.Answer {
			if a.Header().Rrtype == dns.TypeSOA {
				serial = int(a.(*dns.SOA).Serial)
				break Transfer
			}
		}
	}
	if serial == -1 {
		return false, Err
	}
	return less(z.Apex.SOA.Serial, uint32(serial)), Err
}
Beispiel #3
0
func (p Proxy) lookup(state middleware.State, r *dns.Msg) (*dns.Msg, error) {
	var (
		reply *dns.Msg
		err   error
	)
	for _, upstream := range p.Upstreams {
		// allowed bla bla bla TODO(miek): fix full proxy spec from caddy?
		start := time.Now()

		// Since Select() should give us "up" hosts, keep retrying
		// hosts until timeout (or until we get a nil host).
		for time.Now().Sub(start) < tryDuration {
			host := upstream.Select()

			if host == nil {
				return nil, errUnreachable
			}

			atomic.AddInt64(&host.Conns, 1)
			// tls+tcp ?
			if state.Proto() == "tcp" {
				reply, err = middleware.Exchange(p.Client.TCP, r, host.Name)
			} else {
				reply, err = middleware.Exchange(p.Client.UDP, r, host.Name)
			}
			atomic.AddInt64(&host.Conns, -1)

			if err == nil {
				return reply, nil
			}
			timeout := host.FailTimeout
			if timeout == 0 {
				timeout = 10 * time.Second
			}
			atomic.AddInt32(&host.Fails, 1)
			go func(host *UpstreamHost, timeout time.Duration) {
				time.Sleep(timeout)
				atomic.AddInt32(&host.Fails, -1)
			}(host, timeout)
		}
		return nil, errUnreachable
	}
	return nil, errUnreachable
}
Beispiel #4
0
func notifyAddr(c *dns.Client, m *dns.Msg, s string) error {
	for i := 0; i < 3; i++ {
		ret, err := middleware.Exchange(c, m, s)
		if err != nil {
			continue
		}
		if ret.Rcode == dns.RcodeSuccess || ret.Rcode == dns.RcodeNotImplemented {
			return nil
		}
	}
	return fmt.Errorf("Failed to send notify for zone '%s' to '%s'", m.Question[0].Name, s)
}
Beispiel #5
0
func Exchange(m *dns.Msg, server, net string) (*dns.Msg, error) {
	c := new(dns.Client)
	c.Net = net
	return middleware.Exchange(c, m, server)
}