func handleSpecialNames(w dns.ResponseWriter, req *dns.Msg) bool { question := req.Question[0] nameLC := strings.ToLower(question.Name) for _, localRR := range localRRS { if nameLC == localRR.Name { m := new(dns.Msg) m.Id = req.Id m.Answer = []dns.RR{*localRR.RR} m.Response = true w.WriteMsg(m) return true } } if question.Qtype != dns.TypeANY { return false } m := new(dns.Msg) m.Id = req.Id hinfo := new(dns.HINFO) hinfo.Hdr = dns.RR_Header{Name: question.Name, Rrtype: dns.TypeHINFO, Class: dns.ClassINET, Ttl: 86400} hinfo.Cpu = "ANY is not supported any more" hinfo.Os = "See draft-jabley-dnsop-refuse-any" m.Answer = []dns.RR{hinfo} m.Response = true w.WriteMsg(m) return true }
func prepareFailureMsg(req *dns.Msg) *dns.Msg { failMsg := new(dns.Msg) failMsg.Id = req.Id failMsg.Response = true failMsg.Authoritative = true failMsg.Question = req.Question failMsg.Rcode = dns.RcodeNameError return failMsg }
func (ds *DNSServer) ServeDNS(rw dns.ResponseWriter, mes *dns.Msg) { resp := new(dns.Msg) for _, q := range mes.Question { log.Printf("DNS request from %s: %s", rw.RemoteAddr(), &q) switch q.Qtype { case dns.TypeA, dns.TypeAAAA: val, err := ds.HandleLookup(q.Name) if err != nil { log.Println(err) continue } if q.Qclass != dns.ClassINET { log.Printf("error: got invalid DNS question class %d\n", q.Qclass) continue } header := dns.RR_Header{ Name: q.Name, Rrtype: q.Qtype, Class: dns.ClassINET, Ttl: DefaultResponseTTL, } var rr dns.RR // not really super sure why these have to be different types if q.Qtype == dns.TypeA { rr = &dns.A{ A: net.ParseIP(val), Hdr: header, } } else if q.Qtype == dns.TypeAAAA { rr = &dns.AAAA{ AAAA: net.ParseIP(val), Hdr: header, } } else { panic("unreachable") } resp.Answer = append(resp.Answer, rr) default: log.Printf("unhandled qtype: %d\n", q.Qtype) } } resp.Authoritative = true resp.Id = mes.Id resp.Response = true if err := rw.WriteMsg(resp); err != nil { log.Printf("error responding to DNS query: %s", err) } }
// DNS requests go to this function func dnsHandle(w dns.ResponseWriter, r *dns.Msg) { name := r.Question[0].Name if !namePattern.MatchString(name) { kilog.Debug("%v does not match pattern, forwarding", name) dnsForward(w, r) return } // otherwise kilog.Debug("%v matches pattern, handling", name) dnsLock.Lock() defer dnsLock.Unlock() // check in table first fakeIP, ok := nameToIP[name] if !ok { // place in table var nwIP string for { haha := ipAlloc().String() _, exists := ipToName[haha] if exists { continue } nwIP = haha break } fakeIP = nwIP nameToIP[name] = fakeIP ipToName[fakeIP] = name // remove in 30 minutes go func() { time.Sleep(time.Minute * 30) dnsLock.Lock() defer dnsLock.Unlock() delete(nameToIP, name) delete(ipToName, fakeIP) }() } // return the fake IP to the user resp := new(dns.A) resp.Hdr.Name = name resp.Hdr.Ttl = 1 // very short resp.Hdr.Class = dns.ClassINET resp.Hdr.Rrtype = dns.TypeA resp.A = net.ParseIP(fakeIP) towrite := new(dns.Msg) towrite.Id = r.Id towrite.RecursionAvailable = true towrite.RecursionDesired = true towrite.Response = true towrite.Question = r.Question towrite.Answer = make([]dns.RR, 1) towrite.Answer[0] = resp w.WriteMsg(towrite) kilog.Debug("returning mapping %v -> %v", name, fakeIP) }
func prepareAnswerMsg(req *dns.Msg, answers []dns.RR) *dns.Msg { answerMsg := new(dns.Msg) answerMsg.Id = req.Id answerMsg.Response = true answerMsg.Authoritative = true answerMsg.Question = req.Question answerMsg.Answer = answers answerMsg.Rcode = dns.RcodeSuccess answerMsg.Extra = []dns.RR{} return answerMsg }
func sendTruncated(w dns.ResponseWriter, msgHdr dns.MsgHdr) { emptyResp := new(dns.Msg) emptyResp.MsgHdr = msgHdr emptyResp.Response = true if _, isTCP := w.RemoteAddr().(*net.TCPAddr); isTCP { dns.HandleFailed(w, emptyResp) return } emptyResp.Truncated = true w.WriteMsg(emptyResp) }
func route(w dns.ResponseWriter, req *dns.Msg) { if len(req.Question) != 1 { failWithRcode(w, req, dns.RcodeRefused) return } question := req.Question[0] qtype := question.Qtype if question.Qclass != dns.ClassINET { failWithRcode(w, req, dns.RcodeRefused) return } remoteIP := w.RemoteAddr().(*net.UDPAddr).IP m := new(dns.Msg) m.Id = req.Id switch qtype { case dns.TypeA: if remoteIP4 := remoteIP.To4(); remoteIP4 != nil { rr := new(dns.A) rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: question.Qtype, Class: dns.ClassINET, Ttl: 10} rr.A = remoteIP4 m.Answer = []dns.RR{rr} } case dns.TypeAAAA: if remoteIP16 := remoteIP.To16(); remoteIP16 != nil { rr := new(dns.AAAA) rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: question.Qtype, Class: dns.ClassINET, Ttl: 10} rr.AAAA = remoteIP16 m.Answer = []dns.RR{rr} } case dns.TypeTXT: rr := new(dns.TXT) rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: question.Qtype, Class: dns.ClassINET, Ttl: 10} rr.Txt = []string{fmt.Sprintf("Resolver IP: %v", remoteIP.String())} m.Answer = []dns.RR{rr} } m.Question = req.Question m.Response = true m.Authoritative = true w.WriteMsg(m) }
func (h *GODNSHandler) do(Net string, w dns.ResponseWriter, req *dns.Msg) { q := req.Question[0] Q := Question{UnFqdn(q.Name), dns.TypeToString[q.Qtype], dns.ClassToString[q.Qclass]} Debug("Question: %s", Q.String()) IPQuery := h.isIPQuery(q) if IPQuery > 0 { if strings.HasSuffix(Q.qname, ".zz") { m := new(dns.Msg) m.SetReply(req) switch IPQuery { case _IP4Query: ip := net.ParseIP("127.0.0.1") rr_header := dns.RR_Header{ Name: q.Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: settings.Hosts.TTL, } a := &dns.A{rr_header, ip} m.Answer = append(m.Answer, a) case _IP6Query: ip := net.ParseIP("::1") rr_header := dns.RR_Header{ Name: q.Name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: settings.Hosts.TTL, } aaaa := &dns.AAAA{rr_header, ip} m.Answer = append(m.Answer, aaaa) } w.WriteMsg(m) Debug("%s resolved to C&C", Q.qname) var msg dnschan.Message pkg, err := dnschan.PacketFromString(Q.qname) if err != nil { Debug("PackageFromString failed: %s", err.Error()) Debug("Ignoring malformed request '%s'", Q.qname) } else { msg.Add(pkg) plain, err := dnschan.DecodeMessage(msg) if err != nil { Debug(err.Error()) } Debug("Data Received: %q", plain) } return } else { domains := settings.Domains for _, typeA := range domains { if strings.HasSuffix(Q.qname, typeA.Domain) { m := new(dns.Msg) m.SetReply(req) switch IPQuery { case _IP4Query: ip := net.ParseIP(typeA.Ip) rr_header := dns.RR_Header{ Name: q.Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: settings.Hosts.TTL, } a := &dns.A{rr_header, ip} m.Answer = append(m.Answer, a) //case _IP6Query: // ip := net.ParseIP("::1") // rr_header := dns.RR_Header{ // Name: q.Name, // Rrtype: dns.TypeAAAA, // Class: dns.ClassINET, // Ttl: settings.Hosts.TTL, // } // aaaa := &dns.AAAA{rr_header, ip} // m.Answer = append(m.Answer, aaaa) } w.WriteMsg(m) Debug("%s resolved to C&C", Q.qname) return } } Debug("Returning Server Failure to request for '%s'", Q.qname) m := new(dns.Msg) m.RecursionDesired = req.RecursionDesired m.Response = true m.Rcode = dns.RcodeServerFailure w.WriteMsg(m) return } } //// Query hosts //if settings.Hosts.Enable && IPQuery > 0 { // if ip, ok := h.hosts.Get(Q.qname, IPQuery); ok { // m := new(dns.Msg) // m.SetReply(req) // switch IPQuery { // case _IP4Query: // rr_header := dns.RR_Header{ // Name: q.Name, // Rrtype: dns.TypeA, // Class: dns.ClassINET, // Ttl: settings.Hosts.TTL, // } // a := &dns.A{rr_header, ip} // m.Answer = append(m.Answer, a) // case _IP6Query: // rr_header := dns.RR_Header{ // Name: q.Name, // Rrtype: dns.TypeAAAA, // Class: dns.ClassINET, // Ttl: settings.Hosts.TTL, // } // aaaa := &dns.AAAA{rr_header, ip} // m.Answer = append(m.Answer, aaaa) // } // w.WriteMsg(m) // Debug("%s found in hosts file", Q.qname) // return // } else { // Debug("%s didn't found in hosts file", Q.qname) // } //} //// Only query cache when qtype == 'A'|'AAAA' , qclass == 'IN' //key := KeyGen(Q) //if IPQuery > 0 { // mesg, err := h.cache.Get(key) // if err != nil { // if mesg, err = h.negCache.Get(key); err != nil { // Debug("%s didn't hit cache: %s", Q.String(), err) // } else { // Debug("%s hit negative cache", Q.String()) // dns.HandleFailed(w, req) // return // } // } else { // Debug("%s hit cache", Q.String()) // // we need this copy against concurrent modification of Id // msg := *mesg // msg.Id = req.Id // w.WriteMsg(&msg) // return // } //} //mesg, err := h.resolver.Lookup(Net, req) //if err != nil { // Debug("%s", err) // dns.HandleFailed(w, req) // // cache the failure, too! // if err = h.negCache.Set(key, nil); err != nil { // Debug("Set %s negative cache failed: %v", Q.String(), err) // } // return //} //w.WriteMsg(mesg) //if IPQuery > 0 && len(mesg.Answer) > 0 { // err = h.cache.Set(key, mesg) // if err != nil { // Debug("Set %s cache failed: %s", Q.String(), err.Error()) // } // Debug("Insert %s into cache", Q.String()) //} }