mirror of
https://github.com/coredns/coredns.git
synced 2025-10-27 16:24:19 -04:00
add local plugin (#4262)
* add local plugin See: #4260 Signed-off-by: Miek Gieben <miek@miek.nl> * stickler bot Signed-off-by: Miek Gieben <miek@miek.nl> * See Also Signed-off-by: Miek Gieben <miek@miek.nl>
This commit is contained in:
127
plugin/local/local.go
Normal file
127
plugin/local/local.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package local
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/coredns/coredns/plugin"
|
||||
clog "github.com/coredns/coredns/plugin/pkg/log"
|
||||
"github.com/coredns/coredns/request"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
var log = clog.NewWithPlugin("local")
|
||||
|
||||
// Local is a plugin that returns standard replies for local queries.
|
||||
type Local struct {
|
||||
Next plugin.Handler
|
||||
}
|
||||
|
||||
var zones = []string{"localhost.", "0.in-addr.arpa.", "127.in-addr.arpa.", "255.in-addr.arpa."}
|
||||
|
||||
func soaFromOrigin(origin string) []dns.RR {
|
||||
hdr := dns.RR_Header{Name: origin, Ttl: ttl, Class: dns.ClassINET, Rrtype: dns.TypeSOA}
|
||||
return []dns.RR{&dns.SOA{Hdr: hdr, Ns: "localhost.", Mbox: "root.localhost.", Serial: 1, Refresh: 0, Retry: 0, Expire: 0, Minttl: ttl}}
|
||||
}
|
||||
|
||||
func nsFromOrigin(origin string) []dns.RR {
|
||||
hdr := dns.RR_Header{Name: origin, Ttl: ttl, Class: dns.ClassINET, Rrtype: dns.TypeNS}
|
||||
return []dns.RR{&dns.NS{Hdr: hdr, Ns: "localhost."}}
|
||||
}
|
||||
|
||||
// ServeDNS implements the plugin.Handler interface.
|
||||
func (l Local) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
|
||||
state := request.Request{W: w, Req: r}
|
||||
qname := state.QName()
|
||||
|
||||
lc := len("localhost.")
|
||||
if len(state.Name()) > lc && strings.HasPrefix(state.Name(), "localhost.") {
|
||||
// we have multiple labels, but the first one is localhost, intercept this and return 127.0.0.1 or ::1
|
||||
log.Debugf("Intercepting localhost query for %q %s, from %s", state.Name(), state.Type(), state.IP())
|
||||
LocalhostCount.Inc()
|
||||
reply := doLocalhost(state)
|
||||
w.WriteMsg(reply)
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
zone := plugin.Zones(zones).Matches(qname)
|
||||
if zone == "" {
|
||||
return plugin.NextOrFailure(l.Name(), l.Next, ctx, w, r)
|
||||
}
|
||||
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(r)
|
||||
zone = qname[len(qname)-len(zone):]
|
||||
|
||||
switch q := state.Name(); q {
|
||||
case "localhost.", "0.in-addr.arpa.", "127.in-addr.arpa.", "255.in-addr.arpa.":
|
||||
switch state.QType() {
|
||||
case dns.TypeA:
|
||||
if q != "localhost." {
|
||||
// nodata
|
||||
m.Ns = soaFromOrigin(qname)
|
||||
break
|
||||
}
|
||||
|
||||
hdr := dns.RR_Header{Name: qname, Ttl: ttl, Class: dns.ClassINET, Rrtype: dns.TypeA}
|
||||
m.Answer = []dns.RR{&dns.A{Hdr: hdr, A: net.ParseIP("127.0.0.1").To4()}}
|
||||
case dns.TypeAAAA:
|
||||
if q != "localhost." {
|
||||
// nodata
|
||||
m.Ns = soaFromOrigin(qname)
|
||||
break
|
||||
}
|
||||
|
||||
hdr := dns.RR_Header{Name: qname, Ttl: ttl, Class: dns.ClassINET, Rrtype: dns.TypeAAAA}
|
||||
m.Answer = []dns.RR{&dns.AAAA{Hdr: hdr, AAAA: net.ParseIP("::1")}}
|
||||
case dns.TypeSOA:
|
||||
m.Answer = soaFromOrigin(qname)
|
||||
case dns.TypeNS:
|
||||
m.Answer = nsFromOrigin(qname)
|
||||
default:
|
||||
// nodata
|
||||
m.Ns = soaFromOrigin(qname)
|
||||
}
|
||||
case "1.0.0.127.in-addr.arpa.":
|
||||
switch state.QType() {
|
||||
case dns.TypePTR:
|
||||
hdr := dns.RR_Header{Name: qname, Ttl: ttl, Class: dns.ClassINET, Rrtype: dns.TypePTR}
|
||||
m.Answer = []dns.RR{&dns.PTR{Hdr: hdr, Ptr: "localhost."}}
|
||||
default:
|
||||
// nodata
|
||||
m.Ns = soaFromOrigin(zone)
|
||||
}
|
||||
}
|
||||
|
||||
if len(m.Answer) == 0 && len(m.Ns) == 0 {
|
||||
m.Ns = soaFromOrigin(zone)
|
||||
m.Rcode = dns.RcodeNameError
|
||||
}
|
||||
|
||||
w.WriteMsg(m)
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Name implements the plugin.Handler interface.
|
||||
func (l Local) Name() string { return "local" }
|
||||
|
||||
func doLocalhost(state request.Request) *dns.Msg {
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(state.Req)
|
||||
switch state.QType() {
|
||||
case dns.TypeA:
|
||||
hdr := dns.RR_Header{Name: state.QName(), Ttl: ttl, Class: dns.ClassINET, Rrtype: dns.TypeA}
|
||||
m.Answer = []dns.RR{&dns.A{Hdr: hdr, A: net.ParseIP("127.0.0.1").To4()}}
|
||||
case dns.TypeAAAA:
|
||||
hdr := dns.RR_Header{Name: state.QName(), Ttl: ttl, Class: dns.ClassINET, Rrtype: dns.TypeAAAA}
|
||||
m.Answer = []dns.RR{&dns.AAAA{Hdr: hdr, AAAA: net.ParseIP("::1")}}
|
||||
default:
|
||||
// nodata
|
||||
m.Ns = soaFromOrigin(state.QName())
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
const ttl = 604800
|
||||
Reference in New Issue
Block a user