// ServeDNS implements the middleware.Handler interface. func (d Dnssec) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { state := middleware.State{W: w, Req: r} do := state.Do() qname := state.Name() qtype := state.QType() zone := middleware.Zones(d.zones).Matches(qname) if zone == "" { return d.Next.ServeDNS(ctx, w, r) } // Intercept queries for DNSKEY, but only if one of the zones matches the qname, otherwise we let // the query through. if qtype == dns.TypeDNSKEY { for _, z := range d.zones { if qname == z { resp := d.getDNSKEY(state, z, do) state.SizeAndDo(resp) w.WriteMsg(resp) return dns.RcodeSuccess, nil } } } drr := NewDnssecResponseWriter(w, d) return d.Next.ServeDNS(ctx, drr, r) }
// ServeDNS implements the middleware.Handler interface. func (c Cache) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { state := middleware.State{W: w, Req: r} qname := state.Name() qtype := state.QType() zone := middleware.Zones(c.Zones).Matches(qname) if zone == "" { return c.Next.ServeDNS(ctx, w, r) } do := state.Do() // might need more from OPT record? if i, ok := c.get(qname, qtype, do); ok { resp := i.toMsg(r) state.SizeAndDo(resp) w.WriteMsg(resp) cacheHitCount.WithLabelValues(zone).Inc() return dns.RcodeSuccess, nil } cacheMissCount.WithLabelValues(zone).Inc() crr := NewCachingResponseWriter(w, c.cache, c.cap) return c.Next.ServeDNS(ctx, crr, r) }
func (d *DnssecResponseWriter) WriteMsg(res *dns.Msg) error { // By definition we should sign anything that comes back, we should still figure out for // which zone it should be. state := middleware.State{W: d.ResponseWriter, Req: res} qname := state.Name() zone := middleware.Zones(d.d.zones).Matches(qname) if zone == "" { return d.ResponseWriter.WriteMsg(res) } if state.Do() { res = d.d.Sign(state, zone, time.Now().UTC()) } state.SizeAndDo(res) return d.ResponseWriter.WriteMsg(res) }
// Report is a plain reporting function that the server can use for REFUSED and other // queries that are turned down because they don't match any middleware. func Report(state middleware.State, zone, rcode string, size int, start time.Time) { if requestCount == nil { // no metrics are enabled return } // Proto and Family net := state.Proto() fam := "1" if state.Family() == 2 { fam = "2" } typ := state.QType() requestCount.WithLabelValues(zone, net, fam).Inc() requestDuration.WithLabelValues(zone).Observe(float64(time.Since(start) / time.Millisecond)) if state.Do() { requestDo.WithLabelValues(zone).Inc() } if _, known := monitorType[typ]; known { requestType.WithLabelValues(zone, dns.Type(typ).String()).Inc() } else { requestType.WithLabelValues(zone, other).Inc() } if typ == dns.TypeIXFR || typ == dns.TypeAXFR { responseTransferSize.WithLabelValues(zone, net).Observe(float64(size)) requestTransferSize.WithLabelValues(zone, net).Observe(float64(state.Size())) } else { responseSize.WithLabelValues(zone, net).Observe(float64(size)) requestSize.WithLabelValues(zone, net).Observe(float64(state.Size())) } responseRcode.WithLabelValues(zone, rcode).Inc() }
func (f File) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { state := middleware.State{W: w, Req: r} if state.QClass() != dns.ClassINET { return dns.RcodeServerFailure, errors.New("can only deal with ClassINET") } qname := state.Name() zone := middleware.Zones(f.Zones.Names).Matches(qname) if zone == "" { if f.Next != nil { return f.Next.ServeDNS(ctx, w, r) } return dns.RcodeServerFailure, errors.New("no next middleware found") } z, ok := f.Zones.Z[zone] if !ok { return f.Next.ServeDNS(ctx, w, r) } if z == nil { return dns.RcodeServerFailure, nil } if r.Opcode == dns.OpcodeNotify { if z.isNotify(state) { m := new(dns.Msg) m.SetReply(r) m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true state.SizeAndDo(m) w.WriteMsg(m) log.Printf("[INFO] Notify from %s for %s: checking transfer", state.IP(), zone) ok, err := z.shouldTransfer() if ok { z.TransferIn() } else { log.Printf("[INFO] Notify from %s for %s: no serial increase seen", state.IP(), zone) } if err != nil { log.Printf("[WARNING] Notify from %s for %s: failed primary check: %s", state.IP(), zone, err) } return dns.RcodeSuccess, nil } log.Printf("[INFO] Dropping notify from %s for %s", state.IP(), zone) return dns.RcodeSuccess, nil } if z.Expired != nil && *z.Expired { log.Printf("[ERROR] Zone %s is expired", zone) return dns.RcodeServerFailure, nil } if state.QType() == dns.TypeAXFR || state.QType() == dns.TypeIXFR { xfr := Xfr{z} return xfr.ServeDNS(ctx, w, r) } answer, ns, extra, result := z.Lookup(qname, state.QType(), state.Do()) m := new(dns.Msg) m.SetReply(r) m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true m.Answer, m.Ns, m.Extra = answer, ns, extra switch result { case Success: case NoData: case NameError: m.Rcode = dns.RcodeNameError case Delegation: m.Authoritative = false case ServerFailure: return dns.RcodeServerFailure, nil } state.SizeAndDo(m) m, _ = state.Scrub(m) w.WriteMsg(m) return dns.RcodeSuccess, nil }