add AXFR request handling to support slaves
This commit is contained in:
@@ -2,12 +2,48 @@ package nameserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
func (n *Nameserver) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
|
||||
|
||||
if len(r.Question) == 1 {
|
||||
q := r.Question[0]
|
||||
if q.Qtype == dns.TypeAXFR || q.Qtype == dns.TypeIXFR { // Get remote IP
|
||||
remoteIP, _, err := net.SplitHostPort(w.RemoteAddr().String())
|
||||
if err != nil {
|
||||
n.Logger.Errorw("Failed to parse remote address", "err", err)
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(r)
|
||||
m.Rcode = dns.RcodeRefused
|
||||
_ = w.WriteMsg(m)
|
||||
return
|
||||
}
|
||||
|
||||
// Check if remote IP is in slave list
|
||||
allowed := false
|
||||
for _, slave := range n.Config.General.SlaveHosts {
|
||||
if remoteIP == slave {
|
||||
allowed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !allowed {
|
||||
n.Logger.Warnw("AXFR/IXFR request denied", "remote", remoteIP)
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(r)
|
||||
m.Rcode = dns.RcodeRefused
|
||||
_ = w.WriteMsg(m)
|
||||
return
|
||||
}
|
||||
n.handleAXFR(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(r)
|
||||
// handle edns0
|
||||
@@ -161,3 +197,77 @@ func (n *Nameserver) getRecord(name string, qtype uint16) ([]dns.RR, error) {
|
||||
}
|
||||
return rr, nil
|
||||
}
|
||||
|
||||
func (n *Nameserver) handleAXFR(w dns.ResponseWriter, r *dns.Msg) {
|
||||
|
||||
if len(r.Question) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
zone := dns.Fqdn(r.Question[0].Name)
|
||||
|
||||
records, ok := n.Domains[zone]
|
||||
if !ok {
|
||||
m := new(dns.Msg)
|
||||
m.SetRcode(r, dns.RcodeNameError)
|
||||
_ = w.WriteMsg(m)
|
||||
return
|
||||
}
|
||||
|
||||
// AXFR muss über Transfer laufen
|
||||
tr := new(dns.Transfer)
|
||||
|
||||
c := make(chan *dns.Envelope)
|
||||
|
||||
go func() {
|
||||
defer close(c)
|
||||
|
||||
var rr []dns.RR
|
||||
|
||||
// Start SOA
|
||||
rr = append(rr, n.SOA)
|
||||
|
||||
// NS
|
||||
rr = append(rr, records.NS...)
|
||||
|
||||
// Andere Records
|
||||
// rr = append(rr, filterSOA(records.Records)...)
|
||||
rr = append(rr, records.Records...)
|
||||
|
||||
// TXT Records nur für diese Zone!
|
||||
txtRecords, err := n.DB.GetTXTForAllDomains()
|
||||
if err == nil {
|
||||
for _, rec := range txtRecords {
|
||||
if rec.Value == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
fqdn := dns.Fqdn(rec.Subdomain + "." + zone)
|
||||
|
||||
txtRR := &dns.TXT{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: fqdn,
|
||||
Rrtype: dns.TypeTXT,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 1,
|
||||
},
|
||||
Txt: []string{rec.Value},
|
||||
}
|
||||
|
||||
rr = append(rr, txtRR)
|
||||
|
||||
n.Logger.Debugw("handleAXFR TXT Record", "subdomain", rec.Subdomain, "value", rec.Value, "fqdn", fqdn)
|
||||
rr = append(rr, txtRR)
|
||||
}
|
||||
} else {
|
||||
n.Logger.Errorw("Failed to get TXT records for AXFR", "error", err)
|
||||
}
|
||||
|
||||
// End SOA
|
||||
rr = append(rr, n.SOA)
|
||||
|
||||
c <- &dns.Envelope{RR: rr}
|
||||
}()
|
||||
|
||||
_ = tr.Out(w, r, c)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user