// LookupIP returns hostname from PTR record or error. func LookupIP(ip, serverAddr string) ([]string, error) { names := []string{} m := &dns.Msg{} ipArpa, err := dns.ReverseAddr(ip) if err != nil { return names, err } m.SetQuestion(ipArpa, dns.TypePTR) in, err := dns.Exchange(m, serverAddr+":53") if err != nil { return names, err } if len(in.Answer) < 1 { return names, errors.New("no Answer") } for _, a := range in.Answer { if ptr, ok := a.(*dns.PTR); ok { if strings.Contains(ptr.Ptr, strings.Join(strings.Split(ip, "."), "-")) { continue } names = append(names, strings.TrimRight(ptr.Ptr, ".")) } } if len(names) < 1 { return names, errors.New("no PTR") } return names, nil }
func (s *Spy) mutateContainerInCache(id string, status string) { container, err := s.docker.InspectContainer(id) if err != nil { log.Printf("Unable to inspect container %s, skipping", id) return } name := container.Config.Hostname + "." + container.Config.Domainname + "." var running = regexp.MustCompile("start|^Up.*$") var stopping = regexp.MustCompile("die") switch { case running.MatchString(status): log.Printf("Adding record for %v", name) arpa, err := dns.ReverseAddr(container.NetworkSettings.IPAddress) if err != nil { log.Printf("Unable to create ARPA address. Reverse DNS lookup will be unavailable for this container.") } s.dns.cache.Set(name, &Record{ container.NetworkSettings.IPAddress, arpa, name, }) case stopping.MatchString(status): log.Printf("Removing record for %v", name) s.dns.cache.Remove(name) } }
// handlePtr is used to handle "reverse" DNS queries func (d *DNSServer) handlePtr(resp dns.ResponseWriter, req *dns.Msg) { q := req.Question[0] defer func(s time.Time) { d.logger.Printf("[DEBUG] dns: request for %v (%v) from client %s (%s)", q, time.Now().Sub(s), resp.RemoteAddr().String(), resp.RemoteAddr().Network()) }(time.Now()) // Setup the message response m := new(dns.Msg) m.SetReply(req) m.Authoritative = true m.RecursionAvailable = (len(d.recursors) > 0) // Only add the SOA if requested if req.Question[0].Qtype == dns.TypeSOA { d.addSOA(d.domain, m) } datacenter := d.agent.config.Datacenter // Get the QName without the domain suffix qName := strings.ToLower(dns.Fqdn(req.Question[0].Name)) args := structs.DCSpecificRequest{ Datacenter: datacenter, QueryOptions: structs.QueryOptions{ Token: d.agent.config.ACLToken, AllowStale: d.config.AllowStale, }, } var out structs.IndexedNodes // TODO: Replace ListNodes with an internal RPC that can do the filter // server side to avoid transferring the entire node list. if err := d.agent.RPC("Catalog.ListNodes", &args, &out); err == nil { for _, n := range out.Nodes { arpa, _ := dns.ReverseAddr(n.Address) if arpa == qName { ptr := &dns.PTR{ Hdr: dns.RR_Header{Name: q.Name, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: 0}, Ptr: fmt.Sprintf("%s.node.%s.%s", n.Node, datacenter, d.domain), } m.Answer = append(m.Answer, ptr) break } } } // nothing found locally, recurse if len(m.Answer) == 0 { d.handleRecurse(resp, req) return } // Write out the complete response if err := resp.WriteMsg(m); err != nil { d.logger.Printf("[WARN] dns: failed to respond: %v", err) } }
// NewHandler returns a Handler filled from name and ip. func NewHandler(name, ip string) *Handler { reverse, _ := dns.ReverseAddr(ip) return &Handler{ name: name, ip: net.ParseIP(ip), reverse: reverse, } }
// Handler for reverse DNS queries func ptr(w http.ResponseWriter, r *http.Request) { server := r.URL.Query().Get(":server") ip := r.URL.Query().Get(":ip") if arpa, err := dns.ReverseAddr(ip); err == nil { // Valid IP address (IPv4 or IPv6) resolve(w, r, server, arpa, dns.TypePTR) } else { error(w, 400, 403, "Input string is not a valid IP address") } }
func (h *Hostsfile) FindReverse(name string) (host string, err error) { h.hostMutex.RLock() defer h.hostMutex.RUnlock() for _, hostname := range *h.hosts { if r, _ := dns.ReverseAddr(hostname.ip.String()); name == r { host = dns.Fqdn(hostname.domain) break } } return }
func (r *dnsResolver) findReverse(address string) (hosts []string) { r.hostMutex.RLock() defer r.hostMutex.RUnlock() address = strings.ToLower(dns.Fqdn(address)) for _, entry := range r.hosts { if r, _ := dns.ReverseAddr(entry.Address.String()); address == r && len(entry.Names) > 0 { hosts = append(hosts, dns.Fqdn(entry.Names[0])) } } return }
// LookupAddr performs a reverse lookup for the given address, returning a // list of names mapping to that address. func (u *Unbound) LookupAddr(addr string) (name []string, err error) { reverse, err := dns.ReverseAddr(addr) if err != nil { return nil, err } r, err := u.Resolve(reverse, dns.TypePTR, dns.ClassINET) if err != nil { return nil, err } for _, rr := range r.Rr { name = append(name, rr.(*dns.PTR).Ptr) } return }
func Hostname(ctx *Context, ipaddr string, ext Extension) (ReturnType, *ResponseDict) { rd := new(ResponseDict) qname, err := dns.ReverseAddr(ipaddr) if err != nil { fmt.Printf("Invalid IP address: %s\n", ipaddr) return RETURN_GENERIC_ERROR, nil } reply, err := doQuery(ctx, qname, "PTR", "IN", ext) if err != nil { return RETURN_GENERIC_ERROR, rd // temporary } rd.RepliesTree = append(rd.RepliesTree, reply) return RETURN_GOOD, rd }
func LookupIp(ip string) (host string, err error) { if !utilNet.IsValidIpv4(ip) && !utilNet.IsValidIpv6(ip) { return "", e.New("not a valid ip address") } if ip == "127.0.0.1" || ip == "::1" { return "localhost", nil } config, err := dns.ClientConfigFromFile(ConfigurationFile) if err != nil { return "", e.Forward(err) } config.Timeout = Timeout c := new(dns.Client) c.DialTimeout = DialTimeout c.ReadTimeout = ReadTimeout c.WriteTimeout = WriteTimeout m := new(dns.Msg) rev, err := dns.ReverseAddr(ip) if err != nil { return "", e.Forward(err) } m.SetQuestion(rev, dns.TypePTR) var r *dns.Msg for i := 0; i < len(config.Servers); i++ { r, _, err = c.Exchange(m, config.Servers[i]+":"+config.Port) if err != nil { continue } err = nil } if err != nil { return "", e.Forward(err) } if r.Rcode != dns.RcodeSuccess { return "", e.New("can't resolve %v", ip) } for _, a := range r.Answer { if ptr, ok := a.(*dns.PTR); ok { return strings.TrimSuffix(ptr.Ptr, "."), nil } } return "", e.New("no ptr available") }
// Lookup the hostname for an IP address using HypeDNS // This probably needs work but I don't really know what I'm doing :) func reverseHypeDNSLookup(ip string) (response string, err error) { c := new(dns.Client) m := new(dns.Msg) thing, err := dns.ReverseAddr(ip) if err != nil { return } m.SetQuestion(thing, dns.TypePTR) m.RecursionDesired = true r, _, err := c.Exchange(m, "[fc5d:baa5:61fc:6ffd:9554:67f0:e290:7535]:53") if r == nil || err != nil { return } // Stuff must be in the answer section for _, a := range r.Answer { columns := strings.Fields(a.String()) //column 4 holds the ip address return columns[4], nil } return }
func dnsLookup(msg commands.Message, ret commands.MessageFunc) string { var lookupType, lookupAddr string if len(msg.Params) < 2 { return "Usage: .dns [A/AAAA/CNAME/PTR/TXT/SRV] [host]" } else if len(msg.Params) == 2 { lookupType = "A" lookupAddr = msg.Params[1] } else { lookupType = msg.Params[1] lookupAddr = msg.Params[2] } if strings.ToUpper(lookupType) == "PTR" { if addr, err := dns.ReverseAddr(lookupAddr); err == nil { return lookupHelper(msg, ret, dns.TypePTR, addr) } return "Invalid PTR address" } else if _, isdomain := dns.IsDomainName(lookupAddr); isdomain { if querytype, ok := dns.StringToType[strings.ToUpper(lookupType)]; ok { return lookupHelper(msg, ret, querytype, lookupAddr) } } return "" }
func ptrName(address string) string { reverse, err := dns.ReverseAddr(address) if err != nil { return "" } m := &dns.Msg{} m.RecursionDesired = true m.SetQuestion(reverse, dns.TypePTR) // execute the query result, _, err := dnsClient.Exchange(m, net.JoinHostPort(referenceServer, "53")) if result == nil || result.Rcode != dns.RcodeSuccess { return "" } // Add addresses to set for _, a := range result.Answer { if record, ok := a.(*dns.PTR); ok { return record.Ptr } } return "" }
// http://dns.bortzmeyer.org/{+domain}/{querytype}{?format,server,buffersize,dodnssec,tcp,reverse func handler(w http.ResponseWriter, r *http.Request, typ string) { var ( dnstype uint16 ok bool ) lg.Printf("request from %s %s\n", r.RemoteAddr, r.URL) if dnstype, ok = dns.StringToType[typ]; !ok { fmt.Fprintf(w, "Record type "+typ+" does not exist") return } domain := mux.Vars(r)["domain"] domain = html.UnescapeString(domain) u := unbound.New() defer u.Destroy() forward := false format := "html" u.SetOption("module-config:", "iterator") for k, v := range r.URL.Query() { switch k { case "tcp": if v[0] == "1" { u.SetOption("tcp-upstream:", "yes") } case "dodnssec": if v[0] == "1" { u.SetOption("module-config:", "validator iterator") u.SetOption("edns-buffer-size:", "4096") u.AddTa(`;; ANSWER SECTION: . 168307 IN DNSKEY 257 3 8 ( AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQ bSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh /RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWA JQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXp oY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3 LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGO Yl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGc LmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0= ) ; key id = 19036`) } case "buffersize": if err := u.SetOption("edns-buffer-size:", v[0]); err != nil { fmt.Fprintf(w, "Not a valid buffer size: %s", v[0]) return } case "server": if err := u.SetFwd(v[0]); err != nil { fmt.Fprintf(w, "Not a valid server `%s': %s", v[0], err.Error()) return } forward = true case "reverse": if v[0] == "1" { var err error dnstype = dns.TypePTR domain, err = dns.ReverseAddr(domain) if err != nil { fmt.Fprintf(w, "Not a valid IP address: %s", v[0]) return } } case "format": // unsupported format defaut to html for _, f := range []string{"html", "zone", "xml", "json", "text"} { if v[0] == f { format = f } } } } if !forward { u.ResolvConf("/etc/resolv.conf") } d, err := u.Resolve(domain, dnstype, dns.ClassINET) if err != nil { fmt.Fprintf(w, "error") return } if !d.HaveData { fmt.Fprintf(w, "Domain %s (type %s) does not exist", domain, dns.TypeToString[dnstype]) return } switch format { case "json": Json(w, d) case "xml": Xml(w, d) case "html": fallthrough case "text": fallthrough case "zone": Zone(w, d) } }