func (r *DNSProvider) changeRecord(action, fqdn, value string, ttl int) error { // Find the zone for the given fqdn zone, err := acme.FindZoneByFqdn(fqdn, []string{r.nameserver}) if err != nil { return err } // Create RR rr := new(dns.TXT) rr.Hdr = dns.RR_Header{Name: fqdn, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: uint32(ttl)} rr.Txt = []string{value} rrs := []dns.RR{rr} // Create dynamic update packet m := new(dns.Msg) m.SetUpdate(zone) switch action { case "INSERT": // Always remove old challenge left over from who knows what. m.RemoveRRset(rrs) m.Insert(rrs) case "REMOVE": m.Remove(rrs) default: return fmt.Errorf("Unexpected action: %s", action) } // Setup client c := new(dns.Client) c.SingleInflight = true // TSIG authentication / msg signing if len(r.tsigKey) > 0 && len(r.tsigSecret) > 0 { m.SetTsig(dns.Fqdn(r.tsigKey), r.tsigAlgorithm, 300, time.Now().Unix()) c.TsigSecret = map[string]string{dns.Fqdn(r.tsigKey): r.tsigSecret} } // Send the query reply, _, err := c.Exchange(m, r.nameserver) if err != nil { return fmt.Errorf("DNS update failed: %v", err) } if reply != nil && reply.Rcode != dns.RcodeSuccess { return fmt.Errorf("DNS update failed. Server replied: %s", dns.RcodeToString[reply.Rcode]) } return nil }
func (s *jujuNameServer) handleRequest(w dns.ResponseWriter, r *dns.Msg) { m := new(dns.Msg) m.SetReply(r) for _, q := range r.Question { rr, err := s.answer(q) if err != nil { m.SetRcodeFormatError(r) t := new(dns.TXT) t.Hdr = dns.RR_Header{ Name: q.Name, Rrtype: dns.TypeTXT, Class: dns.ClassNONE, } t.Txt = []string{err.Error()} m.Extra = append(m.Extra, t) continue } else if rr != nil { m.Answer = append(m.Answer, rr) } } m.Authoritative = true // recursion isn't really available, but it's apparently // necessary to set this to make nslookup happy. m.RecursionAvailable = true w.WriteMsg(m) }
func Stats_dns_message(message *dns.Msg, writer dns.ResponseWriter) *dns.Msg { for _, stat := range runtime_stats() { txtRR := new(dns.TXT) txtRR.Hdr = dns.RR_Header{Name: conf.Stats_uri, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0} txtRR.Txt = []string{stat} message.Answer = append(message.Answer, txtRR) } return message }
func TestRFC2136ValidUpdatePacket(t *testing.T) { dns.HandleFunc(rfc2136TestZone, serverHandlerPassBackRequest) defer dns.HandleRemove(rfc2136TestZone) server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false) if err != nil { t.Fatalf("Failed to start test server: %v", err) } defer server.Shutdown() rr := new(dns.TXT) rr.Hdr = dns.RR_Header{ Name: rfc2136TestFqdn, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: uint32(rfc2136TestTTL), } rr.Txt = []string{rfc2136TestValue} rrs := make([]dns.RR, 1) rrs[0] = rr m := new(dns.Msg) m.SetUpdate(dns.Fqdn(rfc2136TestZone)) m.Insert(rrs) expectstr := m.String() expect, err := m.Pack() if err != nil { t.Fatalf("Error packing expect msg: %v", err) } provider, err := NewDNSProviderRFC2136(addrstr, rfc2136TestZone, "", "") if err != nil { t.Fatalf("Expected NewDNSProviderRFC2136() to return no error but the error was -> %v", err) } if err := provider.Present(rfc2136TestDomain, "", "1234d=="); err != nil { t.Errorf("Expected Present() to return no error but the error was -> %v", err) } rcvMsg := <-reqChan rcvMsg.Id = m.Id actual, err := rcvMsg.Pack() if err != nil { t.Fatalf("Error packing actual msg: %v", err) } if !bytes.Equal(actual, expect) { tmp := new(dns.Msg) if err := tmp.Unpack(actual); err != nil { t.Fatalf("Error unpacking actual msg: %v", err) } t.Errorf("Expected msg:\n%s", expectstr) t.Errorf("Actual msg:\n%v", tmp) } }
func errorToTxt(err error) dns.RR { if err == nil { return nil } msg := err.Error() if len(msg) > 255 { msg = msg[:255] } t := new(dns.TXT) t.Hdr.Class = dns.ClassCHAOS t.Hdr.Ttl = 0 t.Hdr.Rrtype = dns.TypeTXT t.Hdr.Name = "." t.Txt = []string{msg} return t }
// RR returns an RR representation of s. It is in a condensed form to minimize space // when this is returned in a DNS message. // The RR will look like: // 1.rails.production.east.skydns.local. 300 CH TXT "service1.example.com:8080(10,0,,false)[0,]" // etcd Key Ttl Host:Port < see below > // between parens: (Priority, Weight, Text (only first 200 bytes!), Mail) // between blockquotes: [TargetStrip,Group] // If the record is synthesised by CoreDNS (i.e. no lookup in etcd happened): // // TODO(miek): what to put here? // func (s *Service) RR() *dns.TXT { l := len(s.Text) if l > 200 { l = 200 } t := new(dns.TXT) t.Hdr.Class = dns.ClassCHAOS t.Hdr.Ttl = s.Ttl t.Hdr.Rrtype = dns.TypeTXT t.Hdr.Name = Domain(s.Key) t.Txt = make([]string, 1) t.Txt[0] = fmt.Sprintf("%s:%d(%d,%d,%s,%t)[%d,%s]", s.Host, s.Port, s.Priority, s.Weight, s.Text[:l], s.Mail, s.TargetStrip, s.Group) return t }
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 (r *DNSProviderRFC2136) changeRecord(action, fqdn, value string, ttl int) error { // Create RR rr := new(dns.TXT) rr.Hdr = dns.RR_Header{Name: fqdn, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: uint32(ttl)} rr.Txt = []string{value} rrs := make([]dns.RR, 1) rrs[0] = rr // Create dynamic update packet m := new(dns.Msg) m.SetUpdate(dns.Fqdn(r.zone)) switch action { case "INSERT": m.Insert(rrs) case "REMOVE": m.Remove(rrs) default: return fmt.Errorf("Unexpected action: %s", action) } // Setup client c := new(dns.Client) c.SingleInflight = true // TSIG authentication / msg signing if len(r.tsigKey) > 0 && len(r.tsigSecret) > 0 { m.SetTsig(dns.Fqdn(r.tsigKey), dns.HmacMD5, 300, time.Now().Unix()) c.TsigSecret = map[string]string{dns.Fqdn(r.tsigKey): r.tsigSecret} } // Send the query reply, _, err := c.Exchange(m, r.nameserver) if err != nil { return fmt.Errorf("DNS update failed: %v", err) } if reply != nil && reply.Rcode != dns.RcodeSuccess { return fmt.Errorf("DNS update failed. Server replied: %s", dns.RcodeToString[reply.Rcode]) } return nil }
func answerTXT(q dns.Question, value string) dns.RR { answer := new(dns.TXT) answer.Header().Name = q.Name answer.Header().Rrtype = dns.TypeTXT answer.Header().Class = dns.ClassINET answer.Txt = []string{value} return answer }
func processWOL(cfg *Config, q *dns.Question) dns.RR { hostname := getWOLHostname(q) log.Printf("WoL requested for %s", hostname) err := wakeByHostname(cfg, hostname) status := "OKAY" if err != nil { status = err.Error() } answer := new(dns.TXT) answer.Header().Name = q.Name answer.Header().Rrtype = dns.TypeTXT answer.Header().Class = dns.ClassINET answer.Txt = []string{status} return answer }
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 o := r.IsEdns0(); o != nil { for _, s := range o.Option { switch e := s.(type) { case *dns.EDNS0_SUBNET: log.Printf("Edns0 subnet %s", e.Address) } } } */ 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.TypeAXFR: c := make(chan *dns.Envelope) var e *error if err := dns.TransferOut(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.Envelope{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.TSIG).Hdr.Name, dns.HmacMD5, 300, time.Now().Unix()) } else { println("Status", w.TsigStatus().Error()) } } if *printf { fmt.Printf("%v\n", m.String()) } w.WriteMsg(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) }