// Serve an AXFR (and fallback of IXFR) as well. func (x Xfr) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { state := middleware.State{W: w, Req: r} if !x.TransferAllowed(state) { return dns.RcodeServerFailure, nil } if state.QType() != dns.TypeAXFR && state.QType() != dns.TypeIXFR { return 0, fmt.Errorf("xfr called with non transfer type: %d", state.QType()) } records := x.All() if len(records) == 0 { return dns.RcodeServerFailure, nil } ch := make(chan *dns.Envelope) defer close(ch) tr := new(dns.Transfer) go tr.Out(w, r, ch) j, l := 0, 0 records = append(records, records[0]) // add closing SOA to the end log.Printf("[INFO] Outgoing transfer of %d records of zone %s to %s started", len(records), x.origin, state.IP()) for i, r := range records { l += dns.Len(r) if l > transferLength { ch <- &dns.Envelope{RR: records[j:i]} l = 0 j = i } } if j < len(records) { ch <- &dns.Envelope{RR: records[j:]} } w.Hijack() // w.Close() // Client closes connection return dns.RcodeSuccess, nil }
func handleReflect(w dns.ResponseWriter, r *dns.Msg) { var ( v4 bool rr dns.RR str string a net.IP ) // TC must be done here m := new(dns.Msg) m.SetReply(r) m.Compress = *compress if ip, ok := w.RemoteAddr().(*net.UDPAddr); ok { str = "Port: " + strconv.Itoa(ip.Port) + " (udp)" a = ip.IP v4 = a.To4() != nil } if ip, ok := w.RemoteAddr().(*net.TCPAddr); ok { str = "Port: " + strconv.Itoa(ip.Port) + " (tcp)" a = ip.IP v4 = a.To4() != nil } if v4 { rr = new(dns.RR_A) rr.(*dns.RR_A).Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0} rr.(*dns.RR_A).A = a.To4() } else { rr = new(dns.RR_AAAA) rr.(*dns.RR_AAAA).Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 0} rr.(*dns.RR_AAAA).AAAA = a } t := new(dns.RR_TXT) t.Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0} t.Txt = []string{str} switch r.Question[0].Qtype { case dns.TypeAXFR: c := make(chan *dns.XfrToken) var e *error if err := dns.XfrSend(w, r, c, e); err != nil { close(c) return } soa, _ := dns.NewRR(`whoami.miek.nl. IN SOA elektron.atoom.net. miekg.atoom.net. ( 2009032802 21600 7200 604800 3600)`) c <- &dns.XfrToken{RR: []dns.RR{soa, t, rr, soa}} close(c) w.Hijack() // w.Close() // Client closes return case dns.TypeTXT: m.Answer = append(m.Answer, t) m.Extra = append(m.Extra, rr) default: fallthrough case dns.TypeAAAA, dns.TypeA: m.Answer = append(m.Answer, rr) m.Extra = append(m.Extra, t) } if r.IsTsig() != nil { if w.TsigStatus() == nil { m.SetTsig(r.Extra[len(r.Extra)-1].(*dns.RR_TSIG).Hdr.Name, dns.HmacMD5, 300, time.Now().Unix()) } else { println("Status", w.TsigStatus().Error()) } } if *printf { fmt.Printf("%v\n", m.String()) } w.Write(m) }
// ServeDNS will be called for every DNS request to this server. // It will attempt to provide answers to all questions from the configured zone. func (s *Server) ServeDNS(w dns.ResponseWriter, request *dns.Msg) { // Call `Hijack` since we will handle closing `dns.ResponseWriter` ourselves w.Hijack() // Handle the request go s.handle(w, request) }
func handleReflect(w dns.ResponseWriter, r *dns.Msg) { reflectHandled += 1 if reflectHandled%1000 == 0 { fmt.Printf("Served %d reflections\n", reflectHandled) } var ( v4 bool rr dns.RR str string a net.IP ) m := new(dns.Msg) m.SetReply(r) m.Compress = *compress if ip, ok := w.RemoteAddr().(*net.UDPAddr); ok { str = "Port: " + strconv.Itoa(ip.Port) + " (udp)" a = ip.IP v4 = a.To4() != nil } if ip, ok := w.RemoteAddr().(*net.TCPAddr); ok { str = "Port: " + strconv.Itoa(ip.Port) + " (tcp)" a = ip.IP v4 = a.To4() != nil } if v4 { rr = new(dns.A) rr.(*dns.A).Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0} rr.(*dns.A).A = a.To4() } else { rr = new(dns.AAAA) rr.(*dns.AAAA).Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 0} rr.(*dns.AAAA).AAAA = a } t := new(dns.TXT) t.Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0} t.Txt = []string{str} switch r.Question[0].Qtype { case dns.TypeTXT: m.Answer = append(m.Answer, t) m.Extra = append(m.Extra, rr) default: fallthrough case dns.TypeAAAA, dns.TypeA: m.Answer = append(m.Answer, rr) m.Extra = append(m.Extra, t) case dns.TypeAXFR, dns.TypeIXFR: c := make(chan *dns.Envelope) tr := new(dns.Transfer) defer close(c) err := tr.Out(w, r, c) if err != nil { return } soa, _ := dns.NewRR(`whoami.miek.nl. 0 IN SOA linode.atoom.net. miek.miek.nl. 2009032802 21600 7200 604800 3600`) c <- &dns.Envelope{RR: []dns.RR{soa, t, rr, soa}} w.Hijack() // w.Close() // Client closes connection return } if r.IsTsig() != nil { if w.TsigStatus() == nil { m.SetTsig(r.Extra[len(r.Extra)-1].(*dns.TSIG).Hdr.Name, dns.HmacMD5, 300, time.Now().Unix()) } else { println("Status", w.TsigStatus().Error()) } } if *printf { fmt.Printf("%v\n", m.String()) } // set TC when question is tc.miek.nl. if m.Question[0].Name == "tc.miek.nl." { m.Truncated = true // send half a message buf, _ := m.Pack() w.Write(buf[:len(buf)/2]) return } w.WriteMsg(m) }