Move alias middleware to it's own repo
parent
e46b985808
commit
929d1d4f03
47
README.md
47
README.md
|
@ -1,2 +1,45 @@
|
|||
# alias
|
||||
Middleware for replacing CNAME records on zone apex.
|
||||
|
||||
# Alias middleware
|
||||
|
||||
This middleware eliminates CNAME records from zone apex by making the subsequent resolved records look like they belong to the zone apex. This behaves similarily to [CloudFlare's Zone Flattening](https://support.cloudflare.com/hc/en-us/articles/200169056-CNAME-Flattening-RFC-compliant-support-for-CNAME-at-the-root).
|
||||
|
||||
Preferrably, this should not be used in favour of the RFC drafts for the new [ANAME](https://tools.ietf.org/html/draft-ietf-dnsop-aname-00) records, but the DNS library used by CoreDNS does not support ANAME records yet.
|
||||
|
||||
# Usage
|
||||
|
||||
```
|
||||
$ go get https://github.com/coredns/coredns
|
||||
$ go get https://github.com/serverwentdown/alias
|
||||
$ cd $GOPATH/src/github.com/coredns/coredns
|
||||
$ vim middleware.cfg
|
||||
# Add the line 145:alias:github.com/serverwentdown/alias
|
||||
$ go generate
|
||||
$ go build
|
||||
$ ./coredns -plugins | grep alias
|
||||
```
|
||||
|
||||
This middleware only works with the `file` middleware with `upstream` set, or when A or AAAA records exist alongside the CNAME record.
|
||||
|
||||
```
|
||||
example.com {
|
||||
file example.com.db {
|
||||
upstream 8.8.8.8
|
||||
}
|
||||
alias
|
||||
}
|
||||
```
|
||||
|
||||
All it does is transform records like this:
|
||||
|
||||
```
|
||||
;; ANSWER SECTION:
|
||||
example.com. 300 IN CNAME some.magic.example.org.
|
||||
some.magic.example.org. 299 IN A 123.123.45.67
|
||||
```
|
||||
|
||||
into
|
||||
|
||||
```
|
||||
;; ANSWER SECTION:
|
||||
example.com. 299 IN A 123.123.45.67
|
||||
```
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
package alias
|
||||
|
||||
import (
|
||||
"github.com/coredns/coredns/middleware"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// Rewrite is middleware to rewrite requests internally before being handled.
|
||||
type Alias struct {
|
||||
Next middleware.Handler
|
||||
}
|
||||
|
||||
// ServeDNS implements the middleware.Handler interface.
|
||||
func (al Alias) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
|
||||
mw := NewResponseModifier(w)
|
||||
return middleware.NextOrFailure(al.Name(), al.Next, ctx, mw, r)
|
||||
}
|
||||
|
||||
// Name implements the Handler interface.
|
||||
func (al Alias) Name() string { return "alias" }
|
||||
|
||||
type ResponseModifier struct {
|
||||
dns.ResponseWriter
|
||||
}
|
||||
|
||||
// Returns a dns.Msg modifier that replaces CNAME on root zones with other records.
|
||||
func NewResponseModifier(w dns.ResponseWriter) *ResponseModifier {
|
||||
return &ResponseModifier{
|
||||
ResponseWriter: w,
|
||||
}
|
||||
}
|
||||
|
||||
// WriteMsg records the status code and calls the
|
||||
// underlying ResponseWriter's WriteMsg method.
|
||||
func (r *ResponseModifier) WriteMsg(res *dns.Msg) error {
|
||||
// Guess zone based on authority section.
|
||||
var zone string
|
||||
for i := 0; i < len(res.Ns); i++ {
|
||||
rr := res.Ns[i]
|
||||
if rr.Header().Rrtype == dns.TypeNS {
|
||||
zone = rr.Header().Name
|
||||
}
|
||||
}
|
||||
|
||||
// Find and delete CNAME record on that zone, storing the canonical name.
|
||||
var cname string
|
||||
for i := 0; i < len(res.Answer); i++ {
|
||||
rr := res.Answer[i]
|
||||
if rr.Header().Rrtype == dns.TypeCNAME && rr.Header().Name == zone {
|
||||
cname = rr.(*dns.CNAME).Target
|
||||
// Remove the CNAME record
|
||||
res.Answer = append(res.Answer[:i], res.Answer[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Rename all the records with the above canonical name to the zone name
|
||||
for i := 0; i < len(res.Answer); i++ {
|
||||
rr := res.Answer[i]
|
||||
if rr.Header().Name == cname {
|
||||
rr.Header().Name = zone
|
||||
}
|
||||
}
|
||||
|
||||
return r.ResponseWriter.WriteMsg(res)
|
||||
}
|
||||
|
||||
// Write is a wrapper that records the size of the message that gets written.
|
||||
func (r *ResponseModifier) Write(buf []byte) (int, error) {
|
||||
n, err := r.ResponseWriter.Write(buf)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Hijack implements dns.Hijacker. It simply wraps the underlying
|
||||
// ResponseWriter's Hijack method if there is one, or returns an error.
|
||||
func (r *ResponseModifier) Hijack() {
|
||||
r.ResponseWriter.Hijack()
|
||||
return
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package alias
|
||||
|
||||
import (
|
||||
"github.com/coredns/coredns/core/dnsserver"
|
||||
"github.com/coredns/coredns/middleware"
|
||||
|
||||
"github.com/mholt/caddy"
|
||||
)
|
||||
|
||||
func init() {
|
||||
caddy.RegisterPlugin("alias", caddy.Plugin{
|
||||
ServerType: "dns",
|
||||
Action: setup,
|
||||
})
|
||||
}
|
||||
|
||||
func setup(c *caddy.Controller) error {
|
||||
c.Next()
|
||||
if c.NextArg() {
|
||||
return middleware.Error("alias", c.ArgErr())
|
||||
}
|
||||
|
||||
dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
|
||||
return Alias{Next: next}
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue