mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-31 10:13:14 -04:00 
			
		
		
		
	
		
			
	
	
		
			128 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			128 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|  | 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
 |