func handleXfrOut(d *dns.Conn, i *dns.Msg) os.Error { if i.IsAxfr() { fmt.Printf("Incoming Axfr request seen\n") if i.Question[0].Name == Zone.name { fmt.Printf("Matches current zone\n") if !Zone.correct { fmt.Printf("Zone was not deemed correct\n") if err := d.WriteMsg(i); err != nil { return err } return nil } else { fmt.Printf("Zone was correct\n") } m := make(chan *dns.Xfr) e := make(chan os.Error) go d.XfrWrite(i, m, e) for j := 0; j < Zone.size; j++ { select { case m <- &dns.Xfr{Add: true, RR: Zone.rrs[j]}: // case err := <-e: return err } } close(m) } else { fmt.Printf("No matching zone found\n") if err := d.WriteMsg(i); err != nil { return err } } } return nil }
func main() { var serial *int = flag.Int("serial", 0, "Perform an IXFR with the given serial") var nameserver *string = flag.String("ns", "127.0.0.1:53", "Query this nameserver") // var secret *string = flag.String("secret", "", "Use this secret for TSIG") flag.Parse() zone := flag.Arg(flag.NArg() - 1) client := dns.NewClient() client.Net = "tcp" m := new(dns.Msg) if *serial > 0 { m.SetIxfr(zone, uint32(*serial)) } else { m.SetAxfr(zone) } if err := client.XfrReceive(m, *nameserver); err == nil { for r := range client.ReplyChan { if r.Error != nil { if r.Error == dns.ErrXfrLast { fmt.Printf("%v\n", r.Reply) } break } fmt.Printf("%v\n", r.Reply) } } else { fmt.Printf("Error %v\n", err) } }
func main() { if len(os.Args) != 2 { fmt.Printf("%s DOMAIN\n", os.Args[0]) os.Exit(1) } // Error checking config, _ := dns.ClientConfigFromFile("/etc/resolv.conf") c := dns.NewClient() m := new(dns.Msg) m.SetQuestion(os.Args[1], dns.TypeMX) m.MsgHdr.RecursionDesired = true // Simple sync query, nothing fancy r := c.Exchange(m, config.Servers[0]) if r == nil { os.Exit(1) } if r.Rcode != dns.RcodeSuccess { fmt.Printf(" *** invalid answer name %s after MX query for %s\n", os.Args[1], os.Args[1]) os.Exit(1) } // Stuff must be in the answer section for _, a := range r.Answer { fmt.Printf("%v\n", a) } }
func main() { if len(os.Args) != 2 { fmt.Printf("%s NAMESERVER\n", os.Args[0]) os.Exit(1) } conf, _ := dns.ClientConfigFromFile("/etc/resolv.conf") m := new(dns.Msg) m.Question = make([]dns.Question, 1) c := dns.NewClient() addr := addresses(conf, c, os.Args[1]) if len(addr) == 0 { fmt.Printf("No address found for %s\n", os.Args[1]) os.Exit(1) } for _, a := range addr { m.Question[0] = dns.Question{"version.bind.", dns.TypeTXT, dns.ClassCHAOS} in := c.Exchange(m, a) if in != nil && in.Answer != nil { fmt.Printf("%v\n", in.Answer[0]) } m.Question[0] = dns.Question{"hostname.bind.", dns.TypeTXT, dns.ClassCHAOS} in = c.Exchange(m, a) if in != nil && in.Answer != nil { fmt.Printf("%v\n", in.Answer[0]) } } }
func main() { conf, err := dns.ClientConfigFromFile("/etc/resolv.conf") if len(os.Args) != 2 || err != nil { fmt.Printf("%s DOMAIN\n", os.Args[0]) os.Exit(1) } m := new(dns.Msg) m.SetQuestion(dns.Fqdn(os.Args[1]), dns.TypeDNSKEY) m.SetEdns0(2048, true) c := new(dns.Client) r, _ := c.Exchange(m, conf.Servers[0]+":"+conf.Port) if r == nil { fmt.Printf("*** no answer received for %s\n", os.Args[1]) os.Exit(1) } if r.Rcode != dns.RcodeSuccess { fmt.Printf(" *** invalid answer name %s after DNSKEY query for %s\n", os.Args[1], os.Args[1]) os.Exit(1) } for _, k := range r.Answer { if key, ok := k.(*dns.RR_DNSKEY); ok { key.Hdr.Ttl = 0 for _, alg := range []int{dns.SHA1, dns.SHA256, dns.SHA384} { ds := key.ToDS(alg) fmt.Printf("%v; %d\n", ds, key.Flags) } } } }
func main() { c, _ := dns.ClientConfigFromFile("/etc/resolv.conf") if len(os.Args) != 2 { fmt.Printf("%s DOMAIN\n", os.Args[0]) os.Exit(1) } m := new(dns.Msg) m.Question = make([]dns.Question, 1) d := new(dns.Conn) d.RemoteAddr = c.Servers[0] for _, a := range addresses(d, os.Args[0]) { d.RemoteAddr = a if err := d.Dial("udp"); err != nil { fmt.Printf("%v\n", err) os.Exit(1) } m.Question[0] = dns.Question{"version.bind.", dns.TypeTXT, dns.ClassCHAOS} in, _ := dns.SimpleQuery("udp", d, m) if in != nil && in.Answer != nil { fmt.Printf("%v\n", in.Answer[0]) } m.Question[0] = dns.Question{"hostname.bind.", dns.TypeTXT, dns.ClassCHAOS} in, _ = dns.SimpleQuery("udp", d, m) if in != nil && in.Answer != nil { fmt.Printf("%v\n", in.Answer[0]) } } }
func addresses(d *dns.Conn, name string) []string { m := new(dns.Msg) m.MsgHdr.RecursionDesired = true //only set this bit m.Question = make([]dns.Question, 1) var ips []string m.Question[0] = dns.Question{os.Args[1], dns.TypeA, dns.ClassINET} in, err := dns.SimpleQuery("udp", d, m) if in == nil { fmt.Printf("Nothing recevied: %s\n", err.String()) return nil } if in.Rcode != dns.RcodeSuccess { return nil } // Stuff must be in the answer section for _, a := range in.Answer { ips = append(ips, a.(*dns.RR_A).A.String()+":53") } m.Question[0] = dns.Question{os.Args[1], dns.TypeAAAA, dns.ClassINET} in, err = dns.SimpleQuery("udp", d, m) if in == nil { fmt.Printf("Nothing recevied: %s\n", err.String()) return ips } if in.Rcode != dns.RcodeSuccess { return ips } for _, a := range in.Answer { ips = append(ips, "["+a.(*dns.RR_AAAA).AAAA.String()+"]:53") } return ips }
// Create a dns message from a fingerprint string and // a DNS question. The order of a string is always the same. // .,IN,NS,QUERY,NOERROR,qr,aa,tc,RD,ad,ad,z,1,0,0,1,DO,4096,nsid func (f *fingerprint) msg() *dns.Msg { m := new(dns.Msg) m.MsgHdr.Id = dns.Id() m.Question = make([]dns.Question, 1) m.Question[0] = dns.Question{f.Query.Name, f.Query.Qtype, f.Query.Qclass} m.MsgHdr.Opcode = f.Opcode m.MsgHdr.Rcode = f.Rcode m.MsgHdr.Response = f.Response m.MsgHdr.Authoritative = f.Authoritative m.MsgHdr.Truncated = f.Truncated m.MsgHdr.RecursionDesired = f.RecursionDesired m.MsgHdr.AuthenticatedData = f.AuthenticatedData m.MsgHdr.CheckingDisabled = f.CheckingDisabled m.MsgHdr.Zero = f.Zero if f.Do { // Add an OPT section. m.SetEdns0(0, true) // We have added an OPT RR, set the size. m.Extra[0].(*dns.RR_OPT).SetUDPSize(uint16(f.UDPSize)) if f.Nsid { m.Extra[0].(*dns.RR_OPT).SetNsid("") } } return m }
func newConnMsg(qname, nameserver string, attempts int, qtype, qclass uint16, aa, ad, cd, rd, dnssec, nsid bool) (*dns.Conn, *dns.Msg) { d := new(dns.Conn) d.RemoteAddr = nameserver d.Attempts = attempts m := new(dns.Msg) m.MsgHdr.Authoritative = aa m.MsgHdr.AuthenticatedData = ad m.MsgHdr.CheckingDisabled = cd m.MsgHdr.RecursionDesired = rd m.Question = make([]dns.Question, 1) if dnssec || nsid { opt := new(dns.RR_OPT) opt.SetDo() opt.SetVersion(0) opt.SetUDPSize(dns.DefaultMsgSize) if nsid { opt.SetNsid("") } m.Extra = make([]dns.RR, 1) m.Extra[0] = opt } m.Question[0] = dns.Question{qname, qtype, qclass} m.Id = dns.Id() return d, m }
// Check if we have nsec3 records and if so, check them func nsecCheck(in *dns.Msg) { for _, r := range in.Answer { if r.Header().Rrtype == dns.TypeNSEC3 { goto Check } } for _, r := range in.Ns { if r.Header().Rrtype == dns.TypeNSEC3 { goto Check } } for _, r := range in.Extra { if r.Header().Rrtype == dns.TypeNSEC3 { goto Check } } return Check: w, err := in.Nsec3Verify(in.Question[0]) switch w { case dns.NSEC3_NXDOMAIN: fmt.Printf(";+ [beta] Correct denial of existence (NSEC3/NXDOMAIN)\n") case dns.NSEC3_NODATA: fmt.Printf(";+ [beta] Correct denial of existence (NSEC3/NODATA)\n") default: // w == 0 if err != nil { fmt.Printf(";- [beta] Incorrect denial of existence (NSEC3): %s\n", err.Error()) } } }
func handleXfrIn(i *dns.Msg) os.Error { q := new(dns.Msg) q.SetAxfr(i.Question[0].Name) m := make(chan *dns.Xfr) fmt.Printf("Preparing Xfr for %s\n", i.Question[0].Name) d := new(dns.Conn) d.RemoteAddr = "127.0.0.1:53" err := d.Dial("tcp") if err != nil { return err } defer d.Close() fmt.Printf("Calling 127.0.0.1 successful\n") go d.XfrRead(q, m) Zone.name = i.Question[0].Name j := 0 for x := range m { Zone.rrs[j] = x.RR j++ } fmt.Printf("Success retrieved %s\n", Zone.name) Zone.size = j return nil }
func main() { c, err := dns.ClientConfigFromFile("/etc/resolv.conf") if len(os.Args) != 2 || err != nil { fmt.Printf("%s DOMAIN\n", os.Args[0]) os.Exit(1) } m := new(dns.Msg) m.MsgHdr.RecursionDesired = true //only set this bit m.Question = make([]dns.Question, 1) m.Question[0] = dns.Question{os.Args[1], dns.TypeDNSKEY, dns.ClassINET} d := new(dns.Conn) d.RemoteAddr = c.Servers[0] in, err := dns.SimpleQuery("udp", d, m) if in != nil { if in.Rcode != dns.RcodeSuccess { fmt.Printf(" *** invalid answer name %s after DNSKEY query for %s\n", os.Args[1], os.Args[1]) os.Exit(1) } // Stuff must be in the answer section for _, k := range in.Answer { // Foreach key would need to provide a DS records, both sha1 and sha256 if key, ok := k.(*dns.RR_DNSKEY); ok { ds := key.ToDS(dns.HashSHA1) ds.Hdr.Ttl = 0 fmt.Printf("%v\n", ds) ds = key.ToDS(dns.HashSHA256) ds.Hdr.Ttl = 0 fmt.Printf("%v\n", ds) } } } else { fmt.Printf("*** error: %s\n", err.String()) } }
func send(m *dns.Msg) (o []byte) { var p *dns.Msg for _, c := range qr { p, _ = c.Client.Exchange(m, c.Addr) } o, _ = p.Pack() return }
// For now, we only answer queries for A and NS func respondWithDotBit(msg *dns.Msg, question dns.Question) { // "foo.bar.bit." => ["foo", "bar", "bit"] nameParts := strings.Split(question.Name, ".", -1) var name []string for _, part := range nameParts { if part != "" { name = append(name, part) } } // edge case, if we get "bit." as question.Name // TODO: handle as proper error if len(name) <= 1 { return } // ["foo", "bar", "bit"] => ["foo", "bar"] name = name[0 : len(name)-1] // look up the root "d/bar" record, err := nmcLookup(name[len(name)-1]) if err != nil { LOG.Fatalln(err) } var value NMCValue json.Unmarshal([]uint8(record.Value), &value) msg.Response = true switch question.Qtype { case dns.TypeA: answerA(msg, question, name, value) case dns.TypeAAAA: answerAAAA(msg, question, name, value) //case dns.TypeNS: answerNS(msg) //case dns.TypeMD: answerMD(msg) //case dns.TypeMF: answerMF(msg) //case dns.TypeCNAME: answerCNAME(msg) //case dns.TypeSOA: answerSOA(msg) //case dns.TypeMB: answerMB(msg) //case dns.TypeMG: answerMG(msg) //case dns.TypeMR: answerMR(msg) //case dns.TypeNULL: answerNULL(msg) //case dns.TypeWKS: answerWKS(msg) //case dns.TypePTR: answerPTR(msg) //case dns.TypeHINFO: answerHINFO(msg) //case dns.TypeMINFO: answerMINFO(msg) //case dns.TypeMX: answerMX(msg) //case dns.TypeTXT: answerTXT(msg) //case dns.TypeSRV: answerSRV(msg) default: LOG.Fatalln("Cannot serve name:", name, "qtype:", question.Qtype) msg.Rcode = dns.RcodeNotImplemented } }
func handleNotifyOut(addr string) { if Zone.name == "" || !Zone.correct { return } d := new(dns.Conn) d.RemoteAddr = addr m := new(dns.Msg) m.SetNotify(Zone.name) fmt.Printf("Sending notifies: zone is ok\n") dns.QueryRequest <- &dns.Query{Conn: d, Query: m} }
// Add an entry from the cache. The old entry (if any) gets // overwritten func (c Cache) add(q *dns.Msg) { qname := q.Question[0].Name i := intval(q.Question[0].Qclass, q.Question[0].Qtype) if c[qname] == nil { im := make(map[int][]byte) c[qname] = im } buf, _ := q.Pack() im := c[qname] im[i] = buf }
// Add an entry to the cache. The old entry (if any) gets overwritten func (c Cache) add(q *dns.Msg) { c.rw.Lock() defer c.rw.Unlock() qname := q.Question[0].Name i := intval(q.Question[0].Qclass, q.Question[0].Qtype) if c.data[qname] == nil { im := make(map[int]*item) c.data[qname] = im } buf, _ := q.Pack() im := c.data[qname] im[i] = &item{time.Seconds(), buf} }
func handleNotify(d *dns.Conn, i *dns.Msg) os.Error { if i.IsNotify() { fmt.Printf("Incoming notify seen\n") q := new(dns.Msg) q.SetReply(i) err := d.WriteMsg(q) if err != nil { return err } err = handleXfrIn(i) if err != nil { return err } } return nil }
func respondTo(conn *net.UDPConn, addr *net.UDPAddr, msg *dns.Msg, raw []uint8) { for _, question := range msg.Question { if strings.HasSuffix(question.Name, ".bit.") { respondWithDotBit(msg, question) } else { respondWithFallback(raw, msg, question, options.dnsProxy) } } out, ok := msg.Pack() if ok == true { conn.WriteToUDP(out, addr) } else { LOG.Fatalln("msg.Pack() failed") } }
func delay(m *dns.Msg) (buf []byte) { var ( ok1 bool o *dns.Msg ) if previous, ok1 = checkDelay(); !ok1 { println("Dropping: too often") time.Sleep(NSECDELAY) return } println("Ok: let it through") for _, c := range qr { o, _ = c.Client.Exchange(m, c.Addr) } buf, _ = o.Pack() return }
func main() { serial := flag.Int("serial", 0, "Perform an IXFR with the given serial") nameserver := flag.String("ns", "127.0.0.1:53", "Query this nameserver") tsig := flag.String("tsig", "", "request tsig with key: name:key (only hmac-md5)") flag.Parse() zone := flag.Arg(flag.NArg() - 1) client := new(dns.Client) client.Net = "tcp" m := new(dns.Msg) if *serial > 0 { m.SetIxfr(zone, uint32(*serial)) } else { m.SetAxfr(zone) } if *tsig != "" { a := strings.SplitN(*tsig, ":", 2) name, secret := a[0], a[1] client.TsigSecret = map[string]string{name: secret} m.SetTsig(name, dns.HmacMD5, 300, time.Now().Unix()) } if t, e := client.XfrReceive(m, *nameserver); e == nil { for r := range t { if r.Error == nil { fmt.Printf("%v\n", r.Reply) } } } else { fmt.Printf("Error %v\n", e) } }
func main() { conf, err := dns.ClientConfigFromFile("/etc/resolv.conf") if len(os.Args) != 2 || err != nil { fmt.Printf("%s DOMAIN\n", os.Args[0]) os.Exit(1) } m := new(dns.Msg) m.SetQuestion(os.Args[1], dns.TypeDNSKEY) // Set EDNS0's Do bit e := new(dns.RR_OPT) e.Hdr.Name = "." e.Hdr.Rrtype = dns.TypeOPT e.SetUDPSize(2048) e.SetDo() m.Extra = append(m.Extra, e) c := dns.NewClient() r := c.Exchange(m, conf.Servers[0]) if r == nil { fmt.Printf("*** no answer received for %s\n", os.Args[1]) os.Exit(1) } if r.Rcode != dns.RcodeSuccess { fmt.Printf(" *** invalid answer name %s after DNSKEY query for %s\n", os.Args[1], os.Args[1]) os.Exit(1) } // Stuff must be in the answer section, check len(r.Answer) for _, k := range r.Answer { // Foreach key would need to provide a DS records, both sha1 and sha256 if key, ok := k.(*dns.RR_DNSKEY); ok { key.Hdr.Ttl = 0 ds := key.ToDS(dns.SHA1) fmt.Printf("%v\n", ds) ds = key.ToDS(dns.SHA256) fmt.Printf("%v\n", ds) ds = key.ToDS(dns.SHA384) fmt.Printf("%v\n", ds) } } }
// Get the key from the DNS (uses the local resolver) and return them. // If nothing is found we return nil func getKey(name string, keytag uint16, server string, tcp bool) *dns.RR_DNSKEY { c := dns.NewClient() if tcp { c.Net = "tcp" } m := new(dns.Msg) m.SetQuestion(name, dns.TypeDNSKEY) r, err := c.Exchange(m, server) if err != nil { return nil } for _, k := range r.Answer { if k1, ok := k.(*dns.RR_DNSKEY); ok { if k1.KeyTag() == keytag { return k1 } } } return nil }
func checkcache(m *dns.Msg) (o []byte) { // Check if we have the packet in Cache // if so, return it. Otherwise ask the // server, return that answer and put it // in the cache. o = cache.lookup(m) if o != nil { // octet 1 and 2 contain the Id, set the one for the current pkt dns.RawSetId(o, 0, m.MsgHdr.Id) return } println("Cache miss") var p *dns.Msg for _, c := range qr { p, _ = c.Client.Exchange(m, c.Addr) } cache.add(p) o, _ = p.Pack() return }
func addresses(conf *dns.ClientConfig, c *dns.Client, name string) []string { m4 := new(dns.Msg) m4.SetQuestion(dns.Fqdn(os.Args[1]), dns.TypeA) m6 := new(dns.Msg) m6.SetQuestion(dns.Fqdn(os.Args[1]), dns.TypeAAAA) addr := make(chan []string) defer close(addr) c.Do(m4, conf.Servers[0]+":"+conf.Port, addr, qhandler) c.Do(m6, conf.Servers[0]+":"+conf.Port, addr, qhandler) var ips []string i := 2 // two outstanding queries forever: for { select { case ip := <-addr: ips = append(ips, ip...) i-- if i == 0 { break forever } } } return ips }
func respondWithFallback(raw []uint8, clientMsg *dns.Msg, clientQuestion dns.Question, proxy *net.UDPAddr) { LOG.Println("fallback:", clientQuestion, proxy) conn, err := net.Dial("udp", proxy.String()) if err != nil { LOG.Fatalln(err) } conn.Write(raw) buffer := make([]byte, 1<<15) size, err := conn.Read(buffer) if err != nil { LOG.Fatalln(err, proxy) } msg := &dns.Msg{} msg.Unpack(buffer[0:size]) LOG.Println(msg) for _, answer := range msg.Answer { clientMsg.Answer = append(clientMsg.Answer, answer) } clientMsg.Rcode = msg.Rcode clientMsg.Response = msg.Response clientMsg.Authoritative = msg.Authoritative clientMsg.Recursion_desired = msg.Recursion_desired clientMsg.Recursion_available = msg.Recursion_available }
func send(m *dns.Msg) (buf []byte) { if *verbose { fmt.Printf("--> %s\n", m.Question[0].String()) } var o *dns.Msg var err error for _, c := range qr { o, err = c.Client.Exchange(m, c.Addr) if *verbose { if err == nil { fmt.Printf("<-- %s\n", m.Question[0].String()) } else { fmt.Printf("%s\n", err.Error()) } } } if err == nil { buf, _ = o.Pack() } return }
func main() { var serial *int = flag.Int("serial", 0, "Perform an IXFR with the given serial") var nameserver *string = flag.String("ns", "127.0.0.1:53", "Query this nameserver") flag.Parse() zone := flag.Arg(flag.NArg() - 1) client := dns.NewClient() client.Net = "tcp" m := new(dns.Msg) if *serial > 0 { m.SetIxfr(zone, uint32(*serial)) } else { m.SetAxfr(zone) } axfr, err := client.XfrReceive(m, *nameserver) if err != nil { println(err.String()) } for _, v := range axfr { fmt.Printf("%v\n", v) } }
func main() { if len(os.Args) != 2 { fmt.Printf("%s DOMAIN\n", os.Args[0]) os.Exit(1) } d := new(dns.Conn) c, err := dns.ClientConfigFromFile("/etc/resolv.conf") // Errorchecking d.RemoteAddr = c.Servers[0] m := new(dns.Msg) m.Id = dns.Id() m.MsgHdr.RecursionDesired = true m.Question = make([]dns.Question, 1) m.Question[0] = dns.Question{os.Args[1], dns.TypeMX, dns.ClassINET} err = d.Dial("udp") if err != nil { fmt.Printf("*** error: %s\n", err.String()) os.Exit(1) } in, err := dns.SimpleQuery("udp", d, m) if in != nil { if in.Rcode != dns.RcodeSuccess { fmt.Printf(" *** invalid answer name %s after MX query for %s\n", os.Args[1], os.Args[1]) os.Exit(1) } // Stuff must be in the answer section for _, a := range in.Answer { fmt.Printf("%v\n", a) } } else { fmt.Printf("*** error: %s\n", err.String()) } }
func reply(c *dns.Conn, in *dns.Msg) []byte { m := new(dns.Msg) m.SetReply(in) m.Question = make([]dns.Question, 1) m.Answer = make([]dns.RR, 1) m.Extra = make([]dns.RR, 1) // Copy the question. m.Question[0] = in.Question[0] // Some foo to check if we are called through ip6 or ip4. // We add the correct reply RR. var ad net.IP if c.UDP != nil { ad = c.Addr.(*net.UDPAddr).IP } else { ad = c.Addr.(*net.TCPAddr).IP } if ad.To4() != nil { r := new(dns.RR_A) r.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0} r.A = ad m.Answer[0] = r } else { r := new(dns.RR_AAAA) r.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 0} r.AAAA = ad m.Answer[0] = r } t := new(dns.RR_TXT) t.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0} if c.TCP != nil { t.Txt = "Port: " + strconv.Itoa(c.Port) + " (tcp)" } else { t.Txt = "Port: " + strconv.Itoa(c.Port) + " (udp)" } m.Extra[0] = t b, _ := m.Pack() return b }