* transfer: reply with refused When the *transfer* plugin is not loaded and of the handlers will still see the AXFR/IXFR request because it is not intercepted. They need to reply with REFUSED in that case. Update file, auto and k8s to do this. Add testcase in the file plugin. Ideally *erratic* should be moved over as well, but maybe that's *erratic* This is a bug fix. Signed-off-by: Miek Gieben <miek@miek.nl> * import path Signed-off-by: Miek Gieben <miek@miek.nl>
93 lines
2.2 KiB
Go
93 lines
2.2 KiB
Go
// Package auto implements an on-the-fly loading file backend.
|
|
package auto
|
|
|
|
import (
|
|
"context"
|
|
"regexp"
|
|
"time"
|
|
|
|
"github.com/coredns/coredns/plugin"
|
|
"github.com/coredns/coredns/plugin/file"
|
|
"github.com/coredns/coredns/plugin/metrics"
|
|
"github.com/coredns/coredns/plugin/pkg/upstream"
|
|
"github.com/coredns/coredns/plugin/transfer"
|
|
"github.com/coredns/coredns/request"
|
|
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
type (
|
|
// Auto holds the zones and the loader configuration for automatically loading zones.
|
|
Auto struct {
|
|
Next plugin.Handler
|
|
*Zones
|
|
|
|
metrics *metrics.Metrics
|
|
transfer *transfer.Transfer
|
|
loader
|
|
}
|
|
|
|
loader struct {
|
|
directory string
|
|
template string
|
|
re *regexp.Regexp
|
|
|
|
ReloadInterval time.Duration
|
|
upstream *upstream.Upstream // Upstream for looking up names during the resolution process.
|
|
}
|
|
)
|
|
|
|
// ServeDNS implements the plugin.Handler interface.
|
|
func (a Auto) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
|
|
state := request.Request{W: w, Req: r}
|
|
qname := state.Name()
|
|
|
|
// Precheck with the origins, i.e. are we allowed to look here?
|
|
zone := plugin.Zones(a.Zones.Origins()).Matches(qname)
|
|
if zone == "" {
|
|
return plugin.NextOrFailure(a.Name(), a.Next, ctx, w, r)
|
|
}
|
|
|
|
// Now the real zone.
|
|
zone = plugin.Zones(a.Zones.Names()).Matches(qname)
|
|
if zone == "" {
|
|
return plugin.NextOrFailure(a.Name(), a.Next, ctx, w, r)
|
|
}
|
|
|
|
a.Zones.RLock()
|
|
z, ok := a.Zones.Z[zone]
|
|
a.Zones.RUnlock()
|
|
|
|
if !ok || z == nil {
|
|
return dns.RcodeServerFailure, nil
|
|
}
|
|
|
|
// If transfer is not loaded, we'll see these, answer with refused (no transfer allowed).
|
|
if state.QType() == dns.TypeAXFR || state.QType() == dns.TypeIXFR {
|
|
return dns.RcodeRefused, nil
|
|
}
|
|
|
|
answer, ns, extra, result := z.Lookup(ctx, state, qname)
|
|
|
|
m := new(dns.Msg)
|
|
m.SetReply(r)
|
|
m.Authoritative = true
|
|
m.Answer, m.Ns, m.Extra = answer, ns, extra
|
|
|
|
switch result {
|
|
case file.Success:
|
|
case file.NoData:
|
|
case file.NameError:
|
|
m.Rcode = dns.RcodeNameError
|
|
case file.Delegation:
|
|
m.Authoritative = false
|
|
case file.ServerFailure:
|
|
return dns.RcodeServerFailure, nil
|
|
}
|
|
|
|
w.WriteMsg(m)
|
|
return dns.RcodeSuccess, nil
|
|
}
|
|
|
|
// Name implements the Handler interface.
|
|
func (a Auto) Name() string { return "auto" }
|