diff options
Diffstat (limited to 'plugin/k8s_external/apex.go')
-rw-r--r-- | plugin/k8s_external/apex.go | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/plugin/k8s_external/apex.go b/plugin/k8s_external/apex.go new file mode 100644 index 000000000..f58894817 --- /dev/null +++ b/plugin/k8s_external/apex.go @@ -0,0 +1,110 @@ +package external + +import ( + "github.com/coredns/coredns/plugin/pkg/dnsutil" + "github.com/coredns/coredns/request" + + "github.com/miekg/dns" +) + +// serveApex serves request that hit the zone' apex. A reply is written back to the client. +func (e *External) serveApex(state request.Request) (int, error) { + m := new(dns.Msg) + m.SetReply(state.Req) + switch state.QType() { + case dns.TypeSOA: + m.Answer = []dns.RR{e.soa(state)} + case dns.TypeNS: + m.Answer = []dns.RR{e.ns(state)} + + addr := e.externalAddrFunc(state) + for _, rr := range addr { + rr.Header().Ttl = e.ttl + rr.Header().Name = state.QName() + m.Extra = append(m.Extra, rr) + } + default: + m.Ns = []dns.RR{e.soa(state)} + } + + state.W.WriteMsg(m) + return 0, nil +} + +// serveSubApex serves requests that hit the zones fake 'dns' subdomain where our nameservers live. +func (e *External) serveSubApex(state request.Request) (int, error) { + base, _ := dnsutil.TrimZone(state.Name(), state.Zone) + + m := new(dns.Msg) + m.SetReply(state.Req) + + // base is either dns. of ns1.dns (or another name), if it's longer return nxdomain + switch labels := dns.CountLabel(base); labels { + default: + m.SetRcode(m, dns.RcodeNameError) + m.Ns = []dns.RR{e.soa(state)} + state.W.WriteMsg(m) + return 0, nil + case 2: + nl, _ := dns.NextLabel(base, 0) + ns := base[:nl] + if ns != "ns1." { + // nxdomain + m.SetRcode(m, dns.RcodeNameError) + m.Ns = []dns.RR{e.soa(state)} + state.W.WriteMsg(m) + return 0, nil + } + + addr := e.externalAddrFunc(state) + for _, rr := range addr { + rr.Header().Ttl = e.ttl + rr.Header().Name = state.QName() + switch state.QType() { + case dns.TypeA: + if rr.Header().Rrtype == dns.TypeA { + m.Answer = append(m.Answer, rr) + } + case dns.TypeAAAA: + if rr.Header().Rrtype == dns.TypeAAAA { + m.Answer = append(m.Answer, rr) + } + } + } + + if len(m.Answer) == 0 { + m.Ns = []dns.RR{e.soa(state)} + } + + state.W.WriteMsg(m) + return 0, nil + + case 1: + // nodata for the dns empty non-terminal + m.Ns = []dns.RR{e.soa(state)} + state.W.WriteMsg(m) + return 0, nil + } +} + +func (e *External) soa(state request.Request) *dns.SOA { + header := dns.RR_Header{Name: state.Zone, Rrtype: dns.TypeSOA, Ttl: e.ttl, Class: dns.ClassINET} + + soa := &dns.SOA{Hdr: header, + Mbox: dnsutil.Join(e.hostmaster, e.apex, state.Zone), + Ns: dnsutil.Join("ns1", e.apex, state.Zone), + Serial: 12345, // Also dynamic? + Refresh: 7200, + Retry: 1800, + Expire: 86400, + Minttl: e.ttl, + } + return soa +} + +func (e *External) ns(state request.Request) *dns.NS { + header := dns.RR_Header{Name: state.Zone, Rrtype: dns.TypeNS, Ttl: e.ttl, Class: dns.ClassINET} + ns := &dns.NS{Hdr: header, Ns: dnsutil.Join("ns1", e.apex, state.Zone)} + + return ns +} |