func ( p Proxy ) ServeDNS (w dns.ResponseWriter, r *dns.Msg) { c := dns.NewClient () c.Net = PROTO if TCP_REGEX != nil { for _, q := range r.Question { if TCP_REGEX.MatchString (q.Name) { LOG.Printf ("Tcp proto regex match: %s", q.Name) c.Net = "tcp" break } } } c.ReadTimeout = TIMEOUT c.WriteTimeout = TIMEOUT if rs, err := c.Exchange (r, p.Server()); err == nil { if DEBUG { LOG.Printf ("DEBUG %s\n%v", w.RemoteAddr(), rs) } w.Write (rs) } else { dns.Refused (w, r) LOG.Printf ("%s %s", w.RemoteAddr(), err) } }
func serve(w dns.ResponseWriter, r *dns.Msg, c *Cache) { switch { case r.IsNotify(): if *flaglog { log.Printf("fks-shield: notify/update") } fallthrough case r.IsUpdate(): client := new(dns.Client) if p, e := client.Exchange(r, *server); e == nil { w.WriteMsg(p) } return } if p := c.Find(r); p != nil { b := []byte{byte(r.MsgHdr.Id >> 8), byte(r.MsgHdr.Id)} p = append(b, p...) w.Write(p) return } // Cache miss client := new(dns.Client) if p, e := client.Exchange(r, *server); e == nil { // TODO(mg): If r has edns0 and p has not we create a mismatch here w.WriteMsg(p) c.Insert(p) return } else { log.Printf("fks-shield: failed to get answer " + e.Error()) m := new(dns.Msg) m.SetRcode(r, dns.RcodeServerFailure) w.WriteMsg(m) } }
func (d dnsService) writeLogErr(w dns.ResponseWriter, msg *dns.Msg) { err := w.Write(msg) if err != nil { log.Printf("Error writing response: %v\n%v", err, msg) } }
func proxyServe(w dns.ResponseWriter, req *dns.Msg) { var ( key string m *dns.Msg err error tried bool data []byte id uint16 query []string questions []dns.Question used string ) defer func() { if err := recover(); err != nil { fmt.Println(err) } }() if req.MsgHdr.Response == true { // supposed responses sent to us are bogus return } query = make([]string, len(req.Question)) for i, q := range req.Question { if q.Qtype != dns.TypeAAAA || *ipv6 { questions = append(questions, q) } query[i] = fmt.Sprintf("(%s %s %s)", q.Name, dns.ClassToString[q.Qclass], dns.TypeToString[q.Qtype]) } if len(questions) == 0 { return } req.Question = questions id = req.Id req.Id = 0 key = toMd5(req.String()) req.Id = id if ENCACHE { if reply, ok := conn.Get(key); ok { data, _ = reply.([]byte) } if data != nil && len(data) > 0 { m = &dns.Msg{} m.Unpack(data) m.Id = id err = w.WriteMsg(m) if DEBUG > 0 { log.Printf("id: %5d cache: HIT %v\n", id, query) } goto end } else { if DEBUG > 0 { log.Printf("id: %5d cache: MISS %v\n", id, query) } } } for i, parts := range DNS { dns := parts[0] proto := parts[1] tried = i > 0 if DEBUG > 0 { if tried { log.Printf("id: %5d try: %v %s %s\n", id, query, dns, proto) } else { log.Printf("id: %5d resolve: %v %s %s\n", id, query, dns, proto) } } client := clientUDP if proto == "tcp" { client = clientTCP } m, _, err = client.Exchange(req, dns) if err == nil && len(m.Answer) > 0 { used = dns break } } if err == nil { if DEBUG > 0 { if tried { if len(m.Answer) == 0 { log.Printf("id: %5d failed: %v\n", id, query) } else { log.Printf("id: %5d bingo: %v %s\n", id, query, used) } } } data, err = m.Pack() if err == nil { _, err = w.Write(data) if err == nil { if ENCACHE { m.Id = 0 data, _ = m.Pack() ttl := 0 if len(m.Answer) > 0 { ttl = int(m.Answer[0].Header().Ttl) if ttl < 0 { ttl = 0 } } conn.Set(key, data, time.Second*time.Duration(ttl)) m.Id = id if DEBUG > 0 { log.Printf("id: %5d cache: CACHED %v TTL %v\n", id, query, ttl) } } } } } end: if DEBUG > 1 { fmt.Println(req) if m != nil { fmt.Println(m) } } if err != nil { log.Printf("id: %5d error: %v %s\n", id, query, err) } if DEBUG > 1 { fmt.Println("====================================================") } }
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) }
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) }
func serve(w dns.ResponseWriter, req *dns.Msg, z *Zone) { qtype := req.Question[0].Qtype logPrintf("[zone %s] incoming %s %s %d from %s\n", z.Origin, req.Question[0].Name, dns.Rr_str[qtype], req.MsgHdr.Id, w.RemoteAddr()) // is this safe/atomic or does it need to go through a channel? qCounter++ logPrintln("Got request", req) label := getQuestionName(z, req) var country string if geoIP != nil { ip, _, _ := net.SplitHostPort(w.RemoteAddr().String()) country = strings.ToLower(geoIP.GetCountry(ip)) logPrintln("Country:", ip, country) } m := new(dns.Msg) m.SetReply(req) if e := m.IsEdns0(); e != nil { m.SetEdns0(4096, e.Do()) } m.Authoritative = true // TODO(ask) Fix the findLabels API to make this work better if alias := z.findLabels(label, "", dns.TypeMF); alias != nil && alias.Records[dns.TypeMF] != nil { // We found an alias record, so pretend the question was for that name instead label = alias.firstRR(dns.TypeMF).(*dns.RR_MF).Mf } labels := z.findLabels(label, country, qtype) if labels == nil { if label == "_status" && (qtype == dns.TypeANY || qtype == dns.TypeTXT) { m.Answer = statusRR(z) m.Authoritative = true w.Write(m) return } if label == "_country" && (qtype == dns.TypeANY || qtype == dns.TypeTXT) { h := dns.RR_Header{Ttl: 1, Class: dns.ClassINET, Rrtype: dns.TypeTXT} h.Name = "_country." + z.Origin + "." m.Answer = []dns.RR{&dns.RR_TXT{Hdr: h, Txt: []string{ w.RemoteAddr().String(), string(country), string(countries.CountryContinent[country]), }, }} m.Authoritative = true w.Write(m) return } // return NXDOMAIN m.SetRcode(req, dns.RcodeNameError) m.Authoritative = true m.Ns = []dns.RR{z.SoaRR()} w.Write(m) return } if servers := labels.Picker(qtype, labels.MaxHosts); servers != nil { var rrs []dns.RR for _, record := range servers { rr := record.RR rr.Header().Name = req.Question[0].Name rrs = append(rrs, rr) } m.Answer = rrs } if len(m.Answer) == 0 { if labels := z.Labels[label]; labels != nil { if _, ok := labels.Records[dns.TypeCNAME]; ok { cname := labels.firstRR(dns.TypeCNAME) m.Answer = append(m.Answer, cname) } } else { m.Ns = append(m.Ns, z.SoaRR()) } } logPrintln(m) err := w.Write(m) if err != nil { // if Pack'ing fails the Write fails. Return SERVFAIL. log.Println("Error writing packet", m) dns.HandleFailed(w, req) } return }