aboutsummaryrefslogtreecommitdiff
path: root/plugin/forward/forward.go
diff options
context:
space:
mode:
Diffstat (limited to 'plugin/forward/forward.go')
-rw-r--r--plugin/forward/forward.go36
1 files changed, 28 insertions, 8 deletions
diff --git a/plugin/forward/forward.go b/plugin/forward/forward.go
index 35885008e..8a3e7188c 100644
--- a/plugin/forward/forward.go
+++ b/plugin/forward/forward.go
@@ -20,8 +20,9 @@ import (
// Forward represents a plugin instance that can proxy requests to another (DNS) server. It has a list
// of proxies each representing one upstream proxy.
type Forward struct {
- proxies []*Proxy
- p Policy
+ proxies []*Proxy
+ p Policy
+ hcInterval time.Duration
from string
ignored []string
@@ -31,22 +32,21 @@ type Forward struct {
maxfails uint32
expire time.Duration
- forceTCP bool // also here for testing
- hcInterval time.Duration // also here for testing
+ forceTCP bool // also here for testing
Next plugin.Handler
}
// New returns a new Forward.
func New() *Forward {
- f := &Forward{maxfails: 2, tlsConfig: new(tls.Config), expire: defaultExpire, hcInterval: hcDuration, p: new(random)}
+ f := &Forward{maxfails: 2, tlsConfig: new(tls.Config), expire: defaultExpire, p: new(random), from: ".", hcInterval: hcDuration}
return f
}
// SetProxy appends p to the proxy list and starts healthchecking.
func (f *Forward) SetProxy(p *Proxy) {
f.proxies = append(f.proxies, p)
- go p.healthCheck()
+ p.start(f.hcInterval)
}
// Len returns the number of configured proxies.
@@ -92,7 +92,27 @@ func (f *Forward) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
child.Finish()
}
+ // If you query for instance ANY isc.org; you get a truncated query back which miekg/dns fails to unpack
+ // because the RRs are not finished. The returned message can be useful or useless. Return the original
+ // query with some header bits set that they should retry with TCP.
+ if err == dns.ErrTruncated {
+ // We may or may not have something sensible... if not reassemble something to send to the client.
+ if ret == nil {
+ ret = new(dns.Msg)
+ ret.SetReply(r)
+ ret.Truncated = true
+ ret.Authoritative = true
+ ret.Rcode = dns.RcodeSuccess
+ }
+ err = nil // and reset err to pass this back to the client.
+ }
+
if err != nil {
+ // Kick off health check to see if *our* upstream is broken.
+ if f.maxfails != 0 {
+ proxy.Healthcheck()
+ }
+
if fails < len(f.proxies) {
continue
}
@@ -140,8 +160,8 @@ func (f *Forward) isAllowedDomain(name string) bool {
func (f *Forward) list() []*Proxy { return f.p.List(f.proxies) }
var (
- errInvalidDomain = errors.New("invalid domain for proxy")
- errNoHealthy = errors.New("no healthy proxies")
+ errInvalidDomain = errors.New("invalid domain for forward")
+ errNoHealthy = errors.New("no healthy proxies or upstream error")
errNoForward = errors.New("no forwarder defined")
)