2018-11-01 11:45:32 +00:00
|
|
|
package upstream
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/coredns/coredns/plugin"
|
|
|
|
"github.com/miekg/dns"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"golang.org/x/net/context"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
defaultTimeout = 5 * time.Second
|
|
|
|
)
|
|
|
|
|
|
|
|
// Upstream is a simplified interface for proxy destination
|
|
|
|
type Upstream interface {
|
|
|
|
Exchange(ctx context.Context, query *dns.Msg) (*dns.Msg, error)
|
2018-11-05 17:40:10 +00:00
|
|
|
Close() error
|
2018-11-01 11:45:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// UpstreamPlugin is a simplified DNS proxy using a generic upstream interface
|
|
|
|
type UpstreamPlugin struct {
|
|
|
|
Upstreams []Upstream
|
|
|
|
Next plugin.Handler
|
|
|
|
}
|
|
|
|
|
2018-11-05 17:40:10 +00:00
|
|
|
// Initialize the upstream plugin
|
|
|
|
func New() *UpstreamPlugin {
|
2018-11-05 20:49:31 +00:00
|
|
|
p := &UpstreamPlugin{
|
|
|
|
Upstreams: []Upstream{},
|
|
|
|
}
|
2018-11-05 17:40:10 +00:00
|
|
|
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
2018-11-01 11:45:32 +00:00
|
|
|
// ServeDNS implements interface for CoreDNS plugin
|
2018-11-05 17:40:10 +00:00
|
|
|
func (p *UpstreamPlugin) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
|
2018-11-01 11:45:32 +00:00
|
|
|
var reply *dns.Msg
|
|
|
|
var backendErr error
|
|
|
|
|
2018-11-05 18:19:01 +00:00
|
|
|
for i := range p.Upstreams {
|
|
|
|
upstream := p.Upstreams[i]
|
2018-11-01 11:45:32 +00:00
|
|
|
reply, backendErr = upstream.Exchange(ctx, r)
|
|
|
|
if backendErr == nil {
|
|
|
|
w.WriteMsg(reply)
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return dns.RcodeServerFailure, errors.Wrap(backendErr, "failed to contact any of the upstreams")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Name implements interface for CoreDNS plugin
|
2018-11-05 17:40:10 +00:00
|
|
|
func (p *UpstreamPlugin) Name() string { return "upstream" }
|