Example #1
0
func newRR(q dns.Question, i instance) dns.RR {
	hdr := dns.RR_Header{
		Name:   q.Name,
		Rrtype: q.Qtype,
		Class:  dns.ClassINET,
		Ttl:    defaultTTL,
	}

	switch q.Qtype {
	case dns.TypeA:
		return &dns.A{
			Hdr: hdr,
			A:   i.ip,
		}
	case dns.TypeSRV:
		return &dns.SRV{
			Hdr:      hdr,
			Priority: 0,
			Weight:   0,
			Port:     i.port,
			Target:   dns.Fqdn(i.host),
		}
	case dns.TypeNS:
		return &dns.NS{
			Hdr: hdr,
			Ns:  dns.Fqdn(i.host),
		}
	default:
		panic("unreachable")
	}
}
Example #2
0
func (v *Value) RRs(out []dns.RR, suffix, apexSuffix string) ([]dns.RR, error) {
	il := len(out)
	suffix = dns.Fqdn(suffix)
	apexSuffix = dns.Fqdn(apexSuffix)

	out, _ = v.appendNSs(out, suffix, apexSuffix)
	if len(v.NS) == 0 {
		out, _ = v.appendTranslate(out, suffix, apexSuffix)
		if !v.HasTranslate {
			out, _ = v.appendAlias(out, suffix, apexSuffix)
			if !v.HasAlias {
				out, _ = v.appendIPs(out, suffix, apexSuffix)
				out, _ = v.appendIP6s(out, suffix, apexSuffix)
				out, _ = v.appendTXTs(out, suffix, apexSuffix)
				out, _ = v.appendMXs(out, suffix, apexSuffix)
				out, _ = v.appendSRVs(out, suffix, apexSuffix)
				out, _ = v.appendTLSA(out, suffix, apexSuffix)
			}
		}
	}
	out, _ = v.appendDSs(out, suffix, apexSuffix)

	xout := out[il:]
	for i := range xout {
		h := xout[i].Header()
		if rrtypeHasPrefix(h.Rrtype) {
			h.Name += suffix
		} else {
			h.Name = suffix
		}
	}

	return out, nil
}
Example #3
0
func (r *RFC2136Provider) Init(rootDomainName string) error {
	var host, port, keyName, secret string
	if host = os.Getenv("RFC2136_HOST"); len(host) == 0 {
		return fmt.Errorf("RFC2136_HOST is not set")
	}

	if port = os.Getenv("RFC2136_PORT"); len(port) == 0 {
		return fmt.Errorf("RFC2136_PORT is not set")
	}

	if keyName = os.Getenv("RFC2136_TSIG_KEYNAME"); len(keyName) == 0 {
		return fmt.Errorf("RFC2136_TSIG_KEYNAME is not set")
	}

	if secret = os.Getenv("RFC2136_TSIG_SECRET"); len(secret) == 0 {
		return fmt.Errorf("RFC2136_TSIG_SECRET is not set")
	}

	r.nameserver = net.JoinHostPort(host, port)
	r.zoneName = dns.Fqdn(rootDomainName)
	r.tsigKeyName = dns.Fqdn(keyName)
	r.tsigSecret = secret

	logrus.Infof("Configured %s with zone '%s' and nameserver '%s'",
		r.GetName(), r.zoneName, r.nameserver)

	return nil
}
Example #4
0
File: chaos.go Project: polvi/dns
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
}
Example #5
0
func VerifyTargetHandler(w http.ResponseWriter, req *http.Request) {
	if !checkAuth(req, authuser, authpassword) {
		UnauthorizedResponse(w)
		return
	}

	hostname1 := dns.Fqdn(mux.Vars(req)["hostname1"])
	hostname2 := dns.Fqdn(mux.Vars(req)["hostname2"])
	nocache := req.URL.Query().Get("nocache") != ""

	target_alias := req.URL.Query().Get("target_alias")
	if target_alias != "" {
		target_alias = dns.Fqdn(target_alias)
	}

	vr, err := VerifyTarget(hostname1, hostname2, target_alias, nocache)
	if err != nil {
		w.WriteHeader(500)
		json.NewEncoder(w).Encode(vr.Error)
		return
	}

	json.NewEncoder(w).Encode(vr)
	return
}
Example #6
0
func discoverDNS(domain string, port int) (servers []string, ttl time.Duration, err error) {
	r, _ := region()

	// all DNS queries must use the FQDN
	domain = "txt." + r + "." + dns.Fqdn(domain)
	if _, ok := dns.IsDomainName(domain); !ok {
		err = fmt.Errorf("invalid domain name: '%s' is not a domain name", domain)
		return
	}
	regionRecords, ttl, err := retryingFindTXT(domain)
	if err != nil {
		return
	}

	for _, az := range regionRecords {
		instances, _, er := retryingFindTXT("txt." + dns.Fqdn(az))
		if er != nil {
			continue
		}
		for _, instance := range instances {
			// format the service URL
			servers = append(servers, fmt.Sprintf("http://%s:%d/eureka/v2", instance, port))
		}
	}
	return
}
Example #7
0
func (c *Client) lookupIPs(host string) (ips []net.IP, err error) {
	m := new(dns.Msg)
	for _, resolver := range c.Resolvers {
		m.SetQuestion(dns.Fqdn(host), dns.TypeA)
		if in, err := dns.Exchange(m, resolver); err == nil {
			for _, rr := range in.Answer {
				if a, ok := rr.(*dns.A); ok {
					ips = append(ips, a.A)
				}
			}
		} else {
			log.Debug(err)
		}

		m.SetQuestion(dns.Fqdn(host), dns.TypeAAAA)
		if in, err := dns.Exchange(m, resolver); err == nil {
			for _, rr := range in.Answer {
				if aaaa, ok := rr.(*dns.AAAA); ok {
					ips = append(ips, aaaa.AAAA)
				}
			}
		} else {
			log.Debug(err)
		}
	}
	if len(ips) != 0 {
		return ips, nil
	}

	return net.LookupIP(host)
}
func ParseSOA(d string, r []dns.RR) (*dns.SOA, []*dns.NS, *MyError.MyError) {
	var soa *dns.SOA
	var ns_a []*dns.NS
	for _, v := range r {
		vh := v.Header()
		if vh.Name == dns.Fqdn(d) || dns.IsSubDomain(vh.Name, dns.Fqdn(d)) {
			switch vh.Rrtype {
			case dns.TypeSOA:
				if vv, ok := v.(*dns.SOA); ok {
					//fmt.Print(utils.GetDebugLine(), "ParseSOA:  ", vv)
					soa = vv
					utils.ServerLogger.Debug("ParseSOA: %v", vv)
				}
			case dns.TypeNS:
				if vv, ok := v.(*dns.NS); ok {
					ns_a = append(ns_a, vv)
				}
			default:
				//fmt.Println(utils.GetDebugLine(), " PasreSOA: error unexpect: ", v)
				utils.ServerLogger.Error("ParseSOA: error unexpect %v", v)
			}
		} else {
			//fmt.Print(utils.GetDebugLine(), "ParseSOA 258 ")
			//fmt.Println(utils.GetDebugLine(), vh.Name+" not match "+d)
			utils.ServerLogger.Debug("%s not match %s", vh.Name, d)
			return nil, nil, MyError.NewError(MyError.ERROR_NOTVALID, d+" has no SOA record,try parent")
		}

	}
	if soa != nil {
		return soa, ns_a, nil
	} else {
		return nil, nil, MyError.NewError(MyError.ERROR_NORESULT, "No SOA record for domain "+d)
	}
}
Example #9
0
File: mdns.go Project: zserge/mdns
// Get IP addresses related to the given local hostname
func (m *mdns) Resolve(host string) []net.IP {
	results := make(chan dns.RR)
	m.queries <- &query{
		questions: []dns.Question{
			dns.Question{dns.Fqdn(host), dns.TypeA, dns.ClassINET},
			dns.Question{dns.Fqdn(host), dns.TypeAAAA, dns.ClassINET},
		},
		results: results,
	}
	ipset := map[string]net.IP{}
	ips := []net.IP{}
	for rr := range results {
		var ip net.IP
		switch rr := rr.(type) {
		case *dns.A:
			ip = rr.A
		case *dns.AAAA:
			ip = make([]byte, 16)
			copy(ip, rr.AAAA[:])
		default:
			continue
		}
		if _, ok := ipset[ip.String()]; !ok {
			ipset[ip.String()] = ip
			ips = append(ips, ip)
		}
	}
	return ips
}
Example #10
0
File: service.go Project: ozym/zone
func (s *Service) UpdateAlias(zone string, ttl uint32, from, to *Device) error {
	for _, r := range from.Aliases {
		if to.HasAlias(r) {
			continue
		}
		fmt.Printf("EXTRA ALIAS: %s\n", r)
		cname := &dns.CNAME{
			Hdr:    dns.RR_Header{Name: dns.Fqdn(r), Rrtype: dns.TypeCNAME, Class: dns.ClassINET},
			Target: dns.Fqdn(to.Name),
		}
		fmt.Println(cname)
		if err := s.RemoveRRset(zone, []dns.RR{cname}); err != nil {
			return err
		}
	}

	for _, r := range to.Aliases {
		if from.HasAlias(r) {
			continue
		}
		fmt.Printf("MISSING ALIAS: %s\n", r)
		cname := &dns.CNAME{
			Hdr:    dns.RR_Header{Name: dns.Fqdn(r), Rrtype: dns.TypeCNAME, Class: dns.ClassINET},
			Target: dns.Fqdn(from.Name),
		}
		fmt.Println(cname)
		if err := s.RemoveRRset(zone, []dns.RR{cname}); err != nil {
			return err
		}
		if err := s.Insert(zone, []dns.RR{cname}); err != nil {
			return err
		}
	}
	return nil
}
Example #11
0
File: service.go Project: ozym/zone
// Dynamically remove a full set of RR records stored in DNS
func (s *Service) RemoveName(zone string, rr []dns.RR) error {
	m := new(dns.Msg)

	m.SetUpdate(zone)
	m.SetTsig(dns.Fqdn(s.Key), dns.HmacMD5, 300, time.Now().Unix())
	m.RemoveName(rr)

	h, err := s.ServerPort()
	if err != nil {
		return err
	}

	c := new(dns.Client)
	c.TsigSecret = map[string]string{dns.Fqdn(s.Key): s.Secret}

	r, _, err := c.Exchange(m, h)
	if err != nil {
		return err
	}

	if r.Rcode != dns.RcodeSuccess {
		return errors.New(fmt.Sprintf("invalid exchange answer"))
	}

	return nil
}
Example #12
0
func (answers *Answers) Addresses(clientIp string, fqdn string, cnameParents []dns.RR, depth int) (records []dns.RR, ok bool) {
	fqdn = dns.Fqdn(fqdn)
	log.WithFields(log.Fields{"fqdn": fqdn, "client": clientIp, "depth": depth}).Debug("Trying to resolve addresses")

	// Limit recursing for non-obvious loops
	if len(cnameParents) >= 10 {
		log.WithFields(log.Fields{"fqdn": fqdn, "client": clientIp}).Warn("Followed CNAME too many times ", cnameParents)
		return nil, false
	}

	// Look for a CNAME entry
	result, ok := answers.Matching(dns.TypeCNAME, clientIp, fqdn)
	if ok && len(result) > 0 {
		cname := result[0].(*dns.CNAME)
		log.WithFields(log.Fields{"fqdn": fqdn, "client": clientIp}).Debug("Matched CNAME ", cname.Target)

		// Stop obvious loops
		if dns.Fqdn(cname.Target) == fqdn {
			log.WithFields(log.Fields{"fqdn": fqdn, "client": clientIp}).Warn("CNAME is a loop ", cname.Target)
			return nil, false
		}

		// Recurse to find the eventual A for this CNAME
		children, ok := answers.Addresses(clientIp, dns.Fqdn(cname.Target), append(cnameParents, cname), depth+1)
		if ok && len(children) > 0 {
			log.WithFields(log.Fields{"fqdn": fqdn, "target": cname.Target, "client": clientIp}).Debug("Resolved CNAME ", children)
			records = append(records, cname)
			records = append(records, children...)
			return records, true
		}
	}

	// Look for an A entry
	result, ok = answers.Matching(dns.TypeA, clientIp, fqdn)
	if ok && len(result) > 0 {
		log.WithFields(log.Fields{"fqdn": fqdn, "client": clientIp}).Debug("Matched A ", result)
		shuffle(&result)
		return result, true
	}

	// Try the default section of the config
	if clientIp != DEFAULT_KEY {
		return answers.Addresses(DEFAULT_KEY, fqdn, cnameParents, depth+1)
	}

	// When resolving CNAMES, check recursive server
	if len(cnameParents) > 0 {
		log.WithFields(log.Fields{"fqdn": fqdn, "client": clientIp}).Debug("Trying recursive servers")
		r := new(dns.Msg)
		r.SetQuestion(fqdn, dns.TypeA)
		msg, err := ResolveTryAll(r, answers.Recursers(clientIp))
		if err == nil {
			return msg.Answer, true
		}
	}

	log.WithFields(log.Fields{"fqdn": fqdn, "client": clientIp}).Debug("Did not match anything")
	return nil, false
}
Example #13
0
File: dns.go Project: fcavani/net
func lookupHost(host string, config *dns.ClientConfig) (addrs []string, err error) {
	if utilNet.IsValidIpv4(host) || utilNet.IsValidIpv6(host) {
		return []string{host}, nil
	}
	if host == "localhost" {
		return []string{"127.0.0.1", "::1"}, nil
	}

	c := new(dns.Client)
	c.DialTimeout = DialTimeout
	c.ReadTimeout = ReadTimeout
	c.WriteTimeout = WriteTimeout
	m := new(dns.Msg)
	m.SetQuestion(dns.Fqdn(host), dns.TypeA)
	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 nil, e.Forward(err)
	}
	if r.Rcode != dns.RcodeSuccess {
		return nil, e.New("can't resolve %v", host)
	}

	addrs = make([]string, 0, 10)
	for _, a := range r.Answer {
		if addr, ok := a.(*dns.A); ok {
			addrs = append(addrs, addr.A.String())
		}
	}

	m.SetQuestion(dns.Fqdn(host), dns.TypeAAAA)
	for i := 0; i < len(config.Servers); i++ {
		r, _, err = c.Exchange(m, config.Servers[0]+":"+config.Port)
		if err != nil {
			continue
		}
		err = nil
	}
	if err != nil {
		return nil, e.Forward(err)
	}
	if r.Rcode != dns.RcodeSuccess {
		return nil, e.New("no success")
	}

	for _, a := range r.Answer {
		if addr, ok := a.(*dns.AAAA); ok {
			addrs = append(addrs, addr.AAAA.String())
		}
	}
	return
}
Example #14
0
//todo: complete this func
func InWhiteList(d string) bool {
	d = dns.Fqdn(d)
	for _, x := range RC.Domains {
		if d == dns.Fqdn(x) {
			return true
		}
	}
	return false
}
Example #15
0
// dnsCNAME returns a DNS CNAME record struct
func dnsCNAME(src, dest string) *dns.CNAME {
	return &dns.CNAME{
		Hdr: dns.RR_Header{
			Name:   dns.Fqdn(src),
			Rrtype: dns.TypeCNAME,
			Class:  dns.ClassINET,
		},
		Target: dns.Fqdn(dest),
	}
}
Example #16
0
func setDefaults(config *Config) error {
	if config.ReadTimeout == 0 {
		config.ReadTimeout = 2 * time.Second
	}
	if config.DnsAddr == "" {
		config.DnsAddr = "127.0.0.1:53"
	}
	if config.Domain == "" {
		config.Domain = "skydns.local."
	}
	if config.Hostmaster == "" {
		config.Hostmaster = "hostmaster." + config.Domain
	}
	// People probably don't know that SOA's email addresses cannot
	// contain @-signs, replace them with dots
	config.Hostmaster = dns.Fqdn(strings.Replace(config.Hostmaster, "@", ".", -1))
	if config.MinTtl == 0 {
		config.MinTtl = 60
	}
	if config.Ttl == 0 {
		config.Ttl = 3600
	}
	if config.Priority == 0 {
		config.Priority = 10
	}

	if len(config.Nameservers) == 0 {
		c, err := dns.ClientConfigFromFile("/etc/resolv.conf")
		if err != nil {
			return err
		}
		for _, s := range c.Servers {
			config.Nameservers = append(config.Nameservers, net.JoinHostPort(s, c.Port))
		}
	}
	config.Domain = dns.Fqdn(strings.ToLower(config.Domain))
	config.DomainLabels = dns.CountLabel(config.Domain)
	if config.DNSSEC != "" {
		// For some reason the + are replaces by spaces in etcd. Re-replace them
		keyfile := strings.Replace(config.DNSSEC, " ", "+", -1)
		k, p, err := ParseKeyFile(keyfile)
		if err != nil {
			return err
		}
		if k.Header().Name != dns.Fqdn(config.Domain) {
			return fmt.Errorf("ownername of DNSKEY must match SkyDNS domain")
		}
		k.Header().Ttl = config.Ttl
		config.PubKey = k
		config.KeyTag = k.KeyTag()
		config.PrivKey = p
		config.ClosestEncloser, config.DenyWildcard = newNSEC3CEandWildcard(config.Domain, config.Domain, config.MinTtl)
	}
	return nil
}
Example #17
0
// Deal with the zone options
func configZONE(w dns.ResponseWriter, req *dns.Msg, t *dns.TXT, c *Config) error {
	sx := strings.Split(t.Txt[0], " ")
	if len(sx) == 0 {
		return nil
	}
	switch strings.ToUpper(sx[0]) {
	case "READ":
		if len(sx) != 3 {
			return nil
		}
		logPrintf("config READ %s %s\n", dns.Fqdn(sx[1]), sx[2])
		if e := c.ReadZoneFile(dns.Fqdn(sx[1]), sx[2]); e != nil {
			logPrintf("failed to read %s: %s\n", sx[2], e.Error())
			return e
		}
		logPrintf("config added: READ %s %s\n", dns.Fqdn(sx[1]), sx[2])
		noerr(w, req)
	case "READXFR":
		if len(sx) != 3 {
			return nil
		}
		logPrintf("config READXFR %s %s\n", dns.Fqdn(sx[1]), sx[2])
		if e := c.ReadZoneXfr(dns.Fqdn(sx[1]), sx[2]); e != nil {
			logPrintf("failed to axfr %s: %s\n", sx[2], e.Error())
			return e
		}
		logPrintf("config added: READXFR %s %s\n", dns.Fqdn(sx[1]), sx[2])
		noerr(w, req)
	case "DROP":
		if len(sx) != 2 {
			return nil
		}
		logPrintf("config DROP %s\n", dns.Fqdn(sx[1]))
		if e := c.DropZone(dns.Fqdn(sx[1])); e != nil {
			logPrintf("Failed to drop %s: %s\n", dns.Fqdn(sx[1]), e.Error())
			return e
		}
		logPrintf("config dropped: DROP %s\n", dns.Fqdn(sx[1]))
		noerr(w, req)
	case "LIST":
		logPrintf("config LIST\n")
		m := new(dns.Msg)
		m.SetReply(req)
		// Add the zones to the additional section
		for zone, _ := range c.Zones {
			a, _ := dns.NewRR("ZONE. TXT \"" + zone + "\"")
			m.Extra = append(m.Extra, a)
		}
		m.SetTsig(userFromTsig(req), dns.HmacMD5, 300, time.Now().Unix())
		w.WriteMsg(m)
	}
	return nil
}
Example #18
0
func IsLocalMysqlBackend(d string) bool {
	d = dns.Fqdn(d)
	if !RC.MySQLEnabled {
		return false
	}
	for _, x := range RC.MySQLConf.DomainsInMySQL {
		if d == dns.Fqdn(x) {
			return true
		}
	}
	return false
}
Example #19
0
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
}
Example #20
0
func TestProtocolHandler(t *testing.T) {
	var (
		answers     = rand.Intn(12) + 3
		want        = answers / 2
		testHandler = dns.HandlerFunc(func(w dns.ResponseWriter, r *dns.Msg) {
			res := &dns.Msg{}

			for i := 0; i < answers; i++ {
				rr := &dns.A{
					Hdr: dns.RR_Header{
						Name:   r.Question[0].Name,
						Rrtype: dns.TypeA,
						Class:  dns.ClassINET,
						Ttl:    5,
					},
					A: net.ParseIP(fmt.Sprintf("1.2.3.%d", i)),
				}
				res.Answer = append(res.Answer, rr)
			}

			err := w.WriteMsg(res)
			if err != nil {
				t.Fatalf("write response failed: %s", err)
			}
		})
	)

	w := &testWriter{
		remoteAddr: &net.UDPAddr{},
	}
	m := &dns.Msg{}
	m.SetQuestion(dns.Fqdn("app.glimpse.io"), dns.TypeA)

	protocolHandler(want, testHandler).ServeDNS(w, m)

	if have := len(w.msg.Answer); want != have {
		t.Errorf("want %d answers, have %d", want, have)
	}

	e := &errorWriter{w}
	errorHandler := dns.HandlerFunc(func(w dns.ResponseWriter, req *dns.Msg) {
		err := w.WriteMsg(&dns.Msg{})
		if err == nil {
			t.Fatalf("want WriteMsg() to fail with errorWriter")
		}
	})

	m = &dns.Msg{}
	m.SetQuestion(dns.Fqdn("app.glimpse.io"), dns.TypeA)
	protocolHandler(42, errorHandler).ServeDNS(e, m)
}
Example #21
0
// Newserver returns a new server.
// TODO(miek): multiple ectdAddrs
func NewServer(domain, dnsAddr string, nameservers []string, etcdAddr string) *server {
	s := &server{
		domain:       dns.Fqdn(strings.ToLower(domain)),
		domainLabels: dns.CountLabel(dns.Fqdn(domain)),
		DnsAddr:      dnsAddr,
		client:       etcd.NewClient([]string{etcdAddr}),
		dnsHandler:   dns.NewServeMux(),
		waiter:       new(sync.WaitGroup),
		nameservers:  nameservers,
	}

	// DNS
	s.dnsHandler.Handle(".", s)
	return s
}
Example #22
0
func setDefaults(config *Config) error {
	if config.ReadTimeout == 0 {
		config.ReadTimeout = 2 * time.Second
	}
	if config.DnsAddr == "" {
		config.DnsAddr = "127.0.0.1:53"
	}
	if config.Domain == "" {
		config.Domain = "skydns.local"
	}
	if config.MinTtl == 0 {
		config.MinTtl = 60
	}
	if config.Ttl == 0 {
		config.Ttl = 3600
	}
	if config.Priority == 0 {
		config.Priority = 10
	}

	if len(config.Nameservers) == 0 {
		c, err := dns.ClientConfigFromFile("/etc/resolv.conf")
		if err != nil {
			return err
		}
		for _, s := range c.Servers {
			config.Nameservers = append(config.Nameservers, net.JoinHostPort(s, c.Port))
		}
	}
	config.Domain = dns.Fqdn(strings.ToLower(config.Domain))
	config.DomainLabels = dns.CountLabel(config.Domain)
	if config.DNSSEC != "" {
		// For some reason the + are replaces by spaces in etcd. Re-replace them
		keyfile := strings.Replace(config.DNSSEC, " ", "+", -1)
		k, p, err := ParseKeyFile(keyfile)
		if err != nil {
			return err
		}
		if k.Header().Name != dns.Fqdn(config.Domain) {
			return fmt.Errorf("ownername of DNSKEY must match SkyDNS domain")
		}
		k.Header().Ttl = config.Ttl
		config.PubKey = k
		config.KeyTag = k.KeyTag()
		config.PrivKey = p
	}
	return nil
}
Example #23
0
func (r *resolver) handlePTRQuery(ptr string, query *dns.Msg) (*dns.Msg, error) {
	parts := []string{}

	if strings.HasSuffix(ptr, ptrIPv4domain) {
		parts = strings.Split(ptr, ptrIPv4domain)
	} else if strings.HasSuffix(ptr, ptrIPv6domain) {
		parts = strings.Split(ptr, ptrIPv6domain)
	} else {
		return nil, fmt.Errorf("invalid PTR query, %v", ptr)
	}

	host := r.backend.ResolveIP(parts[0])

	if len(host) == 0 {
		return nil, nil
	}

	logrus.Debugf("Lookup for IP %s: name %s", parts[0], host)
	fqdn := dns.Fqdn(host)

	resp := new(dns.Msg)
	resp.SetReply(query)
	setCommonFlags(resp)

	rr := new(dns.PTR)
	rr.Hdr = dns.RR_Header{Name: ptr, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: respTTL}
	rr.Ptr = fqdn
	resp.Answer = append(resp.Answer, rr)
	return resp, nil
}
Example #24
0
// standardAddress parses an address string into a structured format with separate
// host, and port portions, as well as the original input string.
func standardAddress(str string) (address, error) {
	var err error

	// first check for scheme and strip it off
	input := str

	// separate host and port
	host, port, err := net.SplitHostPort(str)
	if err != nil {
		host, port, err = net.SplitHostPort(str + ":")
		// no error check here; return err at end of function
	}

	if len(host) > 255 {
		return address{}, fmt.Errorf("specified address is too long: %d > 255", len(host))
	}
	_, d := dns.IsDomainName(host)
	if !d {
		return address{}, fmt.Errorf("host is not a valid domain: %s", host)
	}

	// see if we can set port based off scheme
	if port == "" {
		port = "53"
	}

	return address{Original: input, Host: strings.ToLower(dns.Fqdn(host)), Port: port}, err
}
Example #25
0
/* Get a domain's IPs from a specific name server.

Parameters:
    domain      the domain you want to query
    nameserver  name server's IP address
    port        53 in general
    net         tcp or udp
    timeout     in seconds, can be omitted

Here's an example:
    r, e := ARecords("www.example.com", "8.8.8.8", 53, "tcp")
    if e != nil {
        fmt.Println(e)
    } else {
        fmt.Println(r)
    }
*/
func ARecords(domain, nameserver string, port uint16, net string, timeout ...uint8) ([]string, error) {
	var result []string

	if net != "tcp" && net != "udp" {
		return result, errors.New("The parameter 'net' should only be 'tcp' or 'udp'.")
	}

	msg := new(mdns.Msg)
	msg.SetQuestion(mdns.Fqdn(domain), mdns.TypeA)

	var client *mdns.Client
	if len(timeout) > 0 {
		tm := time.Duration(timeout[0]) * time.Second
		client = &mdns.Client{Net: net, DialTimeout: tm, ReadTimeout: tm, WriteTimeout: tm}
	} else {
		client = &mdns.Client{Net: net}
	}

	r, _, err := client.Exchange(msg, fmt.Sprintf("%s:%d", nameserver, port))
	if err != nil {
		return result, err
	}

	for _, i := range r.Answer {
		if t, ok := i.(*mdns.A); ok {
			result = append(result, t.A.String())
		}
	}

	return result, nil
}
Example #26
0
func (d *DNSServer) handleRecursive(client *dns.Client, defaultMaxResponseSize int) func(dns.ResponseWriter, *dns.Msg) {
	return func(w dns.ResponseWriter, req *dns.Msg) {
		d.ns.debugf("recursive request: %+v", *req)

		// Resolve unqualified names locally
		if len(req.Question) == 1 && req.Question[0].Qtype == dns.TypeA {
			hostname := dns.Fqdn(req.Question[0].Name)
			if strings.Count(hostname, ".") == 1 {
				d.handleLocal(defaultMaxResponseSize)(w, req)
				return
			}
		}

		for _, server := range d.upstream.Servers {
			reqCopy := req.Copy()
			reqCopy.Id = dns.Id()
			response, _, err := client.Exchange(reqCopy, fmt.Sprintf("%s:%s", server, d.upstream.Port))
			if err != nil || response == nil {
				d.ns.debugf("error trying %s: %v", server, err)
				continue
			}
			d.ns.debugf("response: %+v", response)
			response.Id = req.Id
			if err := w.WriteMsg(response); err != nil {
				d.ns.infof("error responding: %v", err)
			}
			return
		}

		d.errorResponse(req, dns.RcodeServerFailure, w)
	}
}
Example #27
0
File: stub.go Project: CMGS/skydns
// Look in .../dns/stub/<domain>/xx for msg.Services. Loop through them
// extract <domain> and add them as forwarders (ip:port-combos) for
// the stub zones. Only numeric (i.e. IP address) hosts are used.
func (s *server) UpdateStubZones() {
	stubmap := make(map[string][]string)

	services, err := s.backend.Records("stub.dns."+s.config.Domain, false, net.IP{})
	if err != nil {
		logf("stub zone update failed: %s", err)
		return
	}
	for _, serv := range services {
		if serv.Port == 0 {
			serv.Port = 53
		}
		ip := net.ParseIP(serv.Host)
		if ip == nil {
			logf("stub zone non-address %s seen for: %s", serv.Key, serv.Host)
			continue
		}

		domain := msg.Domain(serv.Key)
		// Chop of left most label, because that is used as the nameserver place holder
		// and drop the right most labels that belong to localDomain.
		labels := dns.SplitDomainName(domain)
		domain = dns.Fqdn(strings.Join(labels[1:len(labels)-dns.CountLabel(s.config.localDomain)], "."))

		// If the remaining name equals s.config.LocalDomain we ignore it.
		if domain == s.config.localDomain {
			logf("not adding stub zone for my own domain")
			continue
		}
		stubmap[domain] = append(stubmap[domain], net.JoinHostPort(serv.Host, strconv.Itoa(serv.Port)))
	}

	s.config.stub = &stubmap
}
Example #28
0
func (self *TrivialDnsServer) redirectQuery(w dns.ResponseWriter, r *dns.Msg, newName string) {
	self.Count("redirected_requests")
	if !strings.HasSuffix(newName, ".") {
		newName = newName + "."
	}

	newR := new(dns.Msg)
	newR.SetQuestion(dns.Fqdn(newName), dns.TypeA)

	if response, _, err := self.exchangeWithUpstream(newR); err == nil {
		ip := self.getSingleSimpleAnswer(response)
		if ip == nil {
			debug("%s redirect to %s yielded no answer", w.RemoteAddr(), newName)
			self.Count("redirected_nowhere")
			self.refuse(w, r)
			return
		}
		self.Count("redirected_successively")
		self.respondSuccessively(w, r, *ip)
	} else {
		self.Count("upstream_errors")
		self.refuse(w, r)
		log.Printf("%s: error: %s", w.RemoteAddr(), err)
	}
}
Example #29
0
func (e Etcd) AAAA(zone string, state middleware.State, previousRecords []dns.RR) (records []dns.RR, debug []msg.Service, err error) {
	services, debug, err := e.records(state, false)
	if err != nil {
		return nil, debug, err
	}

	for _, serv := range services {
		ip := net.ParseIP(serv.Host)
		switch {
		case ip == nil:
			// Try to resolve as CNAME if it's not an IP, but only if we don't create loops.
			if middleware.Name(state.Name()).Matches(dns.Fqdn(serv.Host)) {
				// x CNAME x is a direct loop, don't add those
				continue
			}

			newRecord := serv.NewCNAME(state.QName(), serv.Host)
			if len(previousRecords) > 7 {
				// don't add it, and just continue
				continue
			}
			if isDuplicateCNAME(newRecord, previousRecords) {
				continue
			}

			state1 := copyState(state, serv.Host, state.QType())
			nextRecords, nextDebug, err := e.AAAA(zone, state1, append(previousRecords, newRecord))

			if err == nil {
				// Not only have we found something we should add the CNAME and the IP addresses.
				if len(nextRecords) > 0 {
					records = append(records, newRecord)
					records = append(records, nextRecords...)
					debug = append(debug, nextDebug...)
				}
				continue
			}
			// This means we can not complete the CNAME, try to look else where.
			target := newRecord.Target
			if dns.IsSubDomain(zone, target) {
				// We should already have found it
				continue
			}
			m1, e1 := e.Proxy.Lookup(state, target, state.QType())
			if e1 != nil {
				continue
			}
			// Len(m1.Answer) > 0 here is well?
			records = append(records, newRecord)
			records = append(records, m1.Answer...)
			continue
			// both here again
		case ip.To4() != nil:
			// nada?
		case ip.To4() == nil:
			records = append(records, serv.NewAAAA(state.QName(), ip.To16()))
		}
	}
	return records, debug, nil
}
Example #30
0
// 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)
	}
}