func checkNS(ns *Nameserver, fqdn, fieldPrefix string) (errs map[string][]string) { errs = make(map[string][]string) msg := new(dns.Msg) msg.SetQuestion(fqdn, dns.TypeSOA) msg.RecursionDesired = false server := ns.Name if strings.HasSuffix(ns.Name, fqdn) { server = ns.Glue } client := new(dns.Client) response, _, err := client.Exchange(msg, server+":53") if err == nil { if !response.Authoritative || len(response.Answer) == 0 { errs[fieldPrefix] = append(errs[fieldPrefix], "Not authoritative for domain!") } } else { log.Printf("Error while querying %s [%s]. Details: %s", ns.Name, ns.Glue, err.Error()) errs[fieldPrefix] = append(errs[fieldPrefix], "Fail to query server!") } return }
// Retrieve the MX records for miek.nl. func ExampleMX() { config, _ := dns.ClientConfigFromFile("/etc/resolv.conf") c := new(dns.Client) m := new(dns.Msg) m.SetQuestion("miek.nl.", dns.TypeMX) m.RecursionDesired = true r, _, err := c.Exchange(m, config.Servers[0]+":"+config.Port) if err != nil { return } if r.Rcode != dns.RcodeSuccess { return } for _, a := range r.Answer { if mx, ok := a.(*dns.MX); ok { fmt.Printf("%s\n", mx.String()) } } }
// Retrieve the DNSKEY records of a zone and convert them // to DS records for SHA1, SHA256 and SHA384. func ExampleDS(zone string) { config, _ := dns.ClientConfigFromFile("/etc/resolv.conf") c := new(dns.Client) m := new(dns.Msg) if zone == "" { zone = "miek.nl" } m.SetQuestion(dns.Fqdn(zone), dns.TypeDNSKEY) m.SetEdns0(4096, true) r, _, err := c.Exchange(m, config.Servers[0]+":"+config.Port) if err != nil { return } if r.Rcode != dns.RcodeSuccess { return } for _, k := range r.Answer { if key, ok := k.(*dns.DNSKEY); ok { for _, alg := range []uint8{dns.SHA1, dns.SHA256, dns.SHA384} { fmt.Printf("%s; %d\n", key.ToDS(alg).String(), key.Flags) } } } }
func checkDSs(DSs []*DS, ns *Nameserver, fqdn string) (errs map[string][]string) { if len(ns.Name) == 0 { // Don't need to check DS if the nameserver is empty return } errs = make(map[string][]string) msg := new(dns.Msg) msg.SetQuestion(fqdn, dns.TypeDNSKEY) msg.RecursionDesired = false server := ns.Name if strings.HasSuffix(ns.Name, fqdn) { server = ns.Glue } client := new(dns.Client) response, _, err := client.Exchange(msg, server+":53") if err != nil { log.Printf("Error while querying DNSKEY in %s [%s]. Details: %s", ns.Name, ns.Glue, err.Error()) errs["ds0-keytag"] = append(errs["ds0-keytag"], "Fail to query server "+ns.Name+"!") errs["ds1-keytag"] = append(errs["ds1-keytag"], "Fail to query server "+ns.Name+"!") return } if response.Truncated { client.Net = "tcp" response, _, err = client.Exchange(msg, server+":53") if err != nil { log.Printf("Error while querying DNSKEY in %s [%s]. Details: %s", ns.Name, ns.Glue, err.Error()) errs["ds0-keytag"] = append(errs["ds0-keytag"], "Fail to query server "+ns.Name+"!") errs["ds1-keytag"] = append(errs["ds1-keytag"], "Fail to query server "+ns.Name+"!") return } } ds1 := DSs[0] ds2 := DSs[1] foundDS1 := false foundDS2 := false for _, rr := range response.Answer { if rr.Header().Rrtype == dns.TypeDNSKEY { dnskeyRR := rr.(*dns.DNSKEY) if int(dnskeyRR.KeyTag()) == ds1.KeyTag { foundDS1 = true ds := dnskeyRR.ToDS(ds1.DigestType) if int(ds.Algorithm) != ds1.Algorithm { errs["ds0-algorithm"] = append(errs["ds0-algorithm"], "Algorithm does not match with DNSKEY in "+ns.Name) } else if strings.ToUpper(ds.Digest) != ds1.Digest { errs["ds0-digest"] = append(errs["ds0-digest"], "Digest does not match with DNSKEY in "+ns.Name) } else if dnskeyRR.Flags&dns.SEP == 0 { errs["ds0-keytag"] = append(errs["ds0-keytag"], "DNSKEY is not a SEP in "+ns.Name) } } if int(dnskeyRR.KeyTag()) == ds2.KeyTag { foundDS2 = true ds := dnskeyRR.ToDS(ds2.DigestType) if int(ds.Algorithm) != ds2.Algorithm { errs["ds1-algorithm"] = append(errs["ds1-algorithm"], "Algorithm does not match with DNSKEY in "+ns.Name) } else if strings.ToUpper(ds.Digest) != ds2.Digest { errs["ds1-digest"] = append(errs["ds1-digest"], "Digest does not match with DNSKEY in "+ns.Name) } else if dnskeyRR.Flags&dns.SEP == 0 { errs["ds1-keytag"] = append(errs["ds1-keytag"], "DNSKEY is not a SEP in "+ns.Name) } } } } if !foundDS1 && len(ds1.Digest) > 0 { errs["ds0-keytag"] = append(errs["ds0-keytag"], "Related DNSKEY not found in "+ns.Name) } if !foundDS2 && len(ds2.Digest) > 0 { errs["ds1-keytag"] = append(errs["ds1-keytag"], "Related DNSKEY not found in "+ns.Name) } return }
func retrieveDomains() map[string]*Domain { var domains map[string]*Domain domains = make(map[string]*Domain) client := new(dns.Client) client.TsigSecret = map[string]string{"transfer-key.": "zasDqD5nW1USPh4vhLfDBw=="} client.Net = "tcp" msg := new(dns.Msg) msg.SetAxfr(".") msg.SetTsig("transfer-key.", dns.HmacMD5, 300, time.Now().Unix()) transfer := dns.Transfer{ TsigSecret: map[string]string{"transfer-key.": "zasDqD5nW1USPh4vhLfDBw=="}, } transferChannel, err := transfer.In(msg, "localhost:53") if err != nil { log.Printf("Error retrieving zones: %s", err.Error()) return domains } var glues map[string]string glues = make(map[string]string) for { response, ok := <-transferChannel if !ok { break } if response.Error != nil { log.Printf("Error retrieving zones: %s", response.Error.Error()) return domains } for _, rr := range response.RR { if rr.Header().Name == "." || rr.Header().Name == "music." { continue } if rr.Header().Rrtype == dns.TypeNS { nsRR := rr.(*dns.NS) ns := new(Nameserver) ns.Name = nsRR.Ns domain := domains[rr.Header().Name] if domain == nil { domain = new(Domain) domain.Name = rr.Header().Name } domain.Nameservers = append(domain.Nameservers, ns) domains[rr.Header().Name] = domain } else if rr.Header().Rrtype == dns.TypeDS { dsRR := rr.(*dns.DS) ds := new(DS) ds.KeyTag = int(dsRR.KeyTag) ds.Algorithm = int(dsRR.Algorithm) ds.DigestType = dsRR.DigestType ds.Digest = strings.ToUpper(dsRR.Digest) domain := domains[rr.Header().Name] if domain == nil { domain = new(Domain) domain.Name = rr.Header().Name } domain.DSs = append(domain.DSs, ds) domains[rr.Header().Name] = domain } else if rr.Header().Rrtype == dns.TypeA { aRR := rr.(*dns.A) glues[aRR.Header().Name] = aRR.A.String() } } } for _, domain := range domains { for _, nameserver := range domain.Nameservers { for name, glue := range glues { if nameserver.Name == name { nameserver.Glue = glue } } } } return domains }