transfer: reply with refused (#4510)

* 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>
This commit is contained in:
Miek Gieben 2021-03-09 21:17:34 +01:00 committed by GitHub
parent c27605797b
commit 74ef6e00f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 0 deletions

View file

@ -62,6 +62,11 @@ func (a Auto) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
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)

View file

@ -47,6 +47,11 @@ func (f File) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
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
}
// This is only for when we are a secondary zones.
if r.Opcode == dns.OpcodeNotify {
if z.isNotify(state) {

View file

@ -1,9 +1,15 @@
package file
import (
"context"
"fmt"
"strings"
"testing"
"github.com/coredns/coredns/plugin/pkg/dnstest"
"github.com/coredns/coredns/plugin/test"
"github.com/miekg/dns"
)
func ExampleZone_All() {
@ -41,3 +47,26 @@ func TestAllNewZone(t *testing.T) {
t.Errorf("Expected %d records in empty zone, got %d", 0, len(records))
}
}
func TestAXFRWithOutTransferPlugin(t *testing.T) {
zone, err := Parse(strings.NewReader(dbMiekNL), testzone, "stdin", 0)
if err != nil {
t.Fatalf("Expected no error when reading zone, got %q", err)
}
fm := File{Next: test.ErrorHandler(), Zones: Zones{Z: map[string]*Zone{testzone: zone}, Names: []string{testzone}}}
ctx := context.TODO()
m := new(dns.Msg)
m.SetQuestion("miek.nl.", dns.TypeAXFR)
rec := dnstest.NewRecorder(&test.ResponseWriter{})
code, err := fm.ServeDNS(ctx, rec, m)
if err != nil {
t.Errorf("Expected no error, got %v", err)
return
}
if code != dns.RcodeRefused {
t.Errorf("Expecting REFUSED, got %d", code)
}
}

View file

@ -44,6 +44,8 @@ func (k Kubernetes) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.M
records, extra, err = plugin.SRV(ctx, &k, zone, state, plugin.Options{})
case dns.TypeSOA:
records, err = plugin.SOA(ctx, &k, zone, state, plugin.Options{})
case dns.TypeAXFR, dns.TypeIXFR:
return dns.RcodeRefused, nil
case dns.TypeNS:
if state.Name() == zone {
records, extra, err = plugin.NS(ctx, &k, zone, state, plugin.Options{})