aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/directives.go7
-rw-r--r--middleware/chaos/README.md17
-rw-r--r--middleware/chaos/chaos.go3
-rw-r--r--middleware/etcd/handler.go4
-rw-r--r--middleware/file/file.go5
-rw-r--r--middleware/log/log.go3
-rw-r--r--middleware/middleware.go1
-rw-r--r--middleware/rewrite/README.md3
-rw-r--r--middleware/rewrite/rewrite.go22
-rw-r--r--server/server.go15
10 files changed, 60 insertions, 20 deletions
diff --git a/core/directives.go b/core/directives.go
index c6b7a4b4a..b679fb7e5 100644
--- a/core/directives.go
+++ b/core/directives.go
@@ -51,17 +51,16 @@ var directiveOrder = []directive{
{"shutdown", setup.Shutdown},
// Directives that inject handlers (middleware)
+ {"log", setup.Log},
{"prometheus", setup.Prometheus},
- {"chaos", setup.Chaos},
{"rewrite", setup.Rewrite},
{"loadbalance", setup.Loadbalance},
- {"log", setup.Log},
- {"errors", setup.Errors},
-
{"file", setup.File},
+ {"chaos", setup.Chaos},
{"secondary", setup.Secondary},
{"etcd", setup.Etcd},
{"proxy", setup.Proxy},
+ {"errors", setup.Errors},
}
// RegisterDirective adds the given directive to caddy's list of directives.
diff --git a/middleware/chaos/README.md b/middleware/chaos/README.md
index 45d022fce..1720e918a 100644
--- a/middleware/chaos/README.md
+++ b/middleware/chaos/README.md
@@ -1,6 +1,7 @@
# chaos
-`chaos`
+The `chaos` middleware allows CoreDNS to response to TXT queries in CH class.
+Useful for retrieving version or author information from the server.
## Syntax
@@ -11,16 +12,12 @@ chaos [version] [authors...]
* `version` the version to return, defaults to CoreDNS.
* `authors` what authors to return. No default.
+Note this middleware can only be specified for a zone once. This is because it hijacks
+the zones `version.bind`, `version.server`, `authors.bind`, `hostname.bind` and
+`id.server`, which means it can only be routed to one middleware.
+
## Examples
~~~
-etcd {
- path /skydns
- endpoint endpoint...
- stubzones
-}
+chaos CoreDNS-001 "Miek Gieben" miek@miek.nl
~~~
-
-* `path` /skydns
-* `endpoint` endpoints...
-* `stubzones`
diff --git a/middleware/chaos/chaos.go b/middleware/chaos/chaos.go
index f668d9a4d..f1725495f 100644
--- a/middleware/chaos/chaos.go
+++ b/middleware/chaos/chaos.go
@@ -22,7 +22,10 @@ func (c Chaos) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
if state.QClass() != dns.ClassCHAOS || state.QType() != dns.TypeTXT {
return c.Next.ServeDNS(ctx, w, r)
}
+
m := new(dns.Msg)
+ m.SetReply(r)
+
hdr := dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeTXT, Class: dns.ClassCHAOS, Ttl: 0}
switch state.Name() {
default:
diff --git a/middleware/etcd/handler.go b/middleware/etcd/handler.go
index c7d9aca61..55a5d0fa8 100644
--- a/middleware/etcd/handler.go
+++ b/middleware/etcd/handler.go
@@ -1,6 +1,7 @@
package etcd
import (
+ "fmt"
"strings"
"github.com/miekg/coredns/middleware"
@@ -11,6 +12,9 @@ import (
func (e Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
state := middleware.State{W: w, Req: r}
+ if state.QClass() != dns.ClassINET {
+ return dns.RcodeServerFailure, fmt.Errorf("etcd: can only deal with ClassINET")
+ }
// We need to check stubzones first, because we may get a request for a zone we
// are not auth. for *but* do have a stubzone forward for. If we do the stubzone
diff --git a/middleware/file/file.go b/middleware/file/file.go
index caf0c5fbc..a647f9d12 100644
--- a/middleware/file/file.go
+++ b/middleware/file/file.go
@@ -1,6 +1,7 @@
package file
import (
+ "fmt"
"io"
"log"
@@ -24,6 +25,10 @@ type (
func (f File) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
state := middleware.State{W: w, Req: r}
+ if state.QClass() != dns.ClassINET {
+ return dns.RcodeServerFailure, fmt.Errorf("file: can only deal with ClassINET")
+ }
+
qname := state.Name()
zone := middleware.Zones(f.Zones.Names).Matches(qname)
if zone == "" {
diff --git a/middleware/log/log.go b/middleware/log/log.go
index 998c2b602..ba5dba40c 100644
--- a/middleware/log/log.go
+++ b/middleware/log/log.go
@@ -23,6 +23,7 @@ func (l Logger) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
if middleware.Name(state.Name()).Matches(rule.NameScope) {
responseRecorder := middleware.NewResponseRecorder(w)
rcode, err := l.Next.ServeDNS(ctx, responseRecorder, r)
+
if rcode > 0 {
// There was an error up the chain, but no response has been written yet.
// The error must be handled here so the log entry will record the response size.
@@ -58,7 +59,7 @@ const (
// DefaultLogFilename is the default log filename.
DefaultLogFilename = "query.log"
// CommonLogFormat is the common log format.
- CommonLogFormat = `{remote} ` + CommonLogEmptyValue + ` [{when}] "{type} {name} {proto} {>do} {>bufsize}" {rcode} {size} {duration}`
+ CommonLogFormat = `{remote} ` + CommonLogEmptyValue + ` [{when}] "{type} {class} {name} {proto} {>do} {>bufsize}" {rcode} {size} {duration}`
// CommonLogEmptyValue is the common empty log value.
CommonLogEmptyValue = "-"
// CombinedLogFormat is the combined log format.
diff --git a/middleware/middleware.go b/middleware/middleware.go
index 1ce5f62d6..44e806dde 100644
--- a/middleware/middleware.go
+++ b/middleware/middleware.go
@@ -20,6 +20,7 @@ type (
// If ServeDNS writes to the response body, it should return a status
// code of 0. This signals to other handlers above it that the response
// body is already written, and that they should not write to it also.
+ // TODO(miek): explain return codes better.
//
// If ServeDNS encounters an error, it should return the error value
// so it can be logged by designated error-handling middleware.
diff --git a/middleware/rewrite/README.md b/middleware/rewrite/README.md
index 6b5fb8161..8e5a460f5 100644
--- a/middleware/rewrite/README.md
+++ b/middleware/rewrite/README.md
@@ -16,6 +16,9 @@ rewrite from to
If from *and* to look like a DNS type (`A`, `MX`, etc.) the type of the message will be rewriten,
i.e. to rewrite ANY queries to HINFO, use `rewrite ANY HINFO`.
+If from *and* to look like a DNS class (`IN`, `CH`, or `HS`) the class of the message will be
+rewritten. I.e. to rewrite CH queries to IN use `rewrite CH IN`.
+
If it does not look like a type a name is assumed and the qname in the message is rewritten, this
needs to be a full match of the name `rewrite miek.nl example.org`.
diff --git a/middleware/rewrite/rewrite.go b/middleware/rewrite/rewrite.go
index 7ec8debdb..591598dda 100644
--- a/middleware/rewrite/rewrite.go
+++ b/middleware/rewrite/rewrite.go
@@ -58,24 +58,29 @@ type Rule interface {
// the type of the request is rewritten, otherwise the name is.
// Note: TSIG signed requests will be invalid.
type SimpleRule struct {
- From, To string
- fromType, toType uint16
+ From, To string
+ fromType, toType uint16
+ fromClass, toClass uint16
}
// NewSimpleRule creates a new Simple Rule
func NewSimpleRule(from, to string) SimpleRule {
tpf := dns.StringToType[from]
tpt := dns.StringToType[to]
- // It's only a type if uppercase is used.
+ clf := dns.StringToClass[from]
+ clt := dns.StringToClass[to]
+ // It's only a type/class if uppercase is used.
if from != strings.ToUpper(from) {
tpf = 0
+ clf = 0
from = middleware.Name(from).Normalize()
}
if to != strings.ToUpper(to) {
tpt = 0
+ clt = 0
to = middleware.Name(to).Normalize()
}
- return SimpleRule{From: from, To: to, fromType: tpf, toType: tpt}
+ return SimpleRule{From: from, To: to, fromType: tpf, toType: tpt, fromClass: clf, toClass: clt}
}
// Rewrite rewrites the the current request.
@@ -89,6 +94,15 @@ func (s SimpleRule) Rewrite(r *dns.Msg) Result {
return RewriteIgnored
}
+ // class rewrite
+ if s.fromClass > 0 && s.toClass > 0 {
+ if r.Question[0].Qclass == s.fromClass {
+ r.Question[0].Qclass = s.toClass
+ return RewriteDone
+ }
+ return RewriteIgnored
+ }
+
// name rewite
if s.From == r.Question[0].Name {
r.Question[0].Name = s.To
diff --git a/server/server.go b/server/server.go
index 1c588b69f..c186c82d2 100644
--- a/server/server.go
+++ b/server/server.go
@@ -17,6 +17,7 @@ import (
"golang.org/x/net/context"
+ "github.com/miekg/coredns/middleware/chaos"
"github.com/miekg/dns"
)
@@ -97,7 +98,6 @@ func New(addr string, configs []Config, gracefulTimeout time.Duration) (*Server,
// Set up each zone
for _, conf := range configs {
- // TODO(miek): something better here?
if _, exists := s.zones[conf.Host]; exists {
return nil, fmt.Errorf("cannot serve %s - host already defined for address %s", conf.Address(), s.Addr)
}
@@ -111,6 +111,19 @@ func New(addr string, configs []Config, gracefulTimeout time.Duration) (*Server,
}
s.zones[conf.Host] = z
+
+ // A bit of a hack. Loop through the middlewares of this zone and check if
+ // they have enabled the chaos middleware. If so add the special chaos zones.
+ Middleware:
+ for _, mid := range z.config.Middleware {
+ fn := mid(nil)
+ if _, ok := fn.(chaos.Chaos); ok {
+ for _, ch := range []string{"authors.bind.", "version.bind.", "version.server.", "hostname.bind.", "id.server."} {
+ s.zones[ch] = z
+ }
+ break Middleware
+ }
+ }
}
return s, nil