Exemple #1
0
func TestDNSUpstreamEncoding(t *testing.T) {
	var tmp [60]byte
	bad_domain := "www." + base32.StdEncoding.EncodeToString(tmp[:]) + "."

	if _, good := dns.IsDomainName(bad_domain); good {
		t.Errorf("Bad domain not detected: %v", bad_domain)
	}

	codec, err := NewDNSTransportUpstreamCodec("blahgeek.com")
	if err != nil {
		t.Fatalf("Unable to build codec: %v", err)
	}
	streamer := DNSTransportStream{codec: codec}

	for i := 0; i < 1500; i += 1 {
		var msg []byte
		for j := 0; j < i; j += 1 {
			msg = append(msg, byte(rand.Int()&0xff))
		}
		var decoded_msg []byte
		upstreams := streamer.Encode(msg)
		for _, d := range upstreams {
			t.Logf("Encoded domain for msg length %v: %v", i, d)
			if _, good := dns.IsDomainName(d); !good {
				t.Errorf("Bad domain for msg length %v", i)
			}
			decoded_msg = streamer.Decode(d)
		}
		if bytes.Compare(decoded_msg, msg) != 0 {
			t.Errorf("Decoded msg != msg")
		}
	}
}
Exemple #2
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
}
Exemple #3
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
}
Exemple #4
0
// update record
func updateRecord(r dns.RR, q *dns.Question) {

	// record to update
	var rr dns.RR
	// IP of record
	var ip net.IP

	header := r.Header()
	if _, ok := dns.IsDomainName(header.Name); ok {
		if header.Class == dns.ClassANY && header.Rdlength == 0 { // Delete record
			deleteRecord(header.Name, header.Rrtype)
		} else { // Add record
			rheader := dns.RR_Header{
				Name:   header.Name,
				Rrtype: header.Rrtype,
				Class:  dns.ClassINET,
				Ttl:    header.Ttl,
			}

			// IPv4 only
			if a, ok := r.(*dns.A); ok {
				rrr, err := getRecord(header.Name, header.Rrtype)
				if err == nil {
					rr = rrr.(*dns.A)
				} else {
					rr = new(dns.A)
				}
				ip = a.A
				rr.(*dns.A).Hdr = rheader
				rr.(*dns.A).A = ip
				saveRecord(rr)
			}
		}
	}
}
Exemple #5
0
func getKey(domain string, rtype uint16) (r string, e error) {
	if *debug {
		Log.Printf("getKey:  domain: %s, resource type: %d\n", domain, rtype)
	}

	if n, ok := dns.IsDomainName(domain); ok {
		labels := dns.SplitDomainName(domain)

		// Reverse domain, starting from top-level domain
		// eg.  ".com.mkaczanowski.test "
		var tmp string
		for i := 0; i < int(math.Floor(float64(n/2))); i++ {
			tmp = labels[i]
			labels[i] = labels[n-1]
			labels[n-1] = tmp
		}

		reverseDomain := strings.Join(labels, ".")
		r = strings.Join([]string{reverseDomain, strconv.Itoa(int(rtype))}, "_")
	} else {
		e = errors.New("Invailid domain: " + domain)
		Log.Println(e.Error())
	}

	return r, e
}
Exemple #6
0
// return formated key (domain_type)
func formatKey(domain string, rtype uint16) (key string, err error) {
	domain = strings.ToLower(domain)
	if _, ok := dns.IsDomainName(domain); !ok {
		return "", errors.New(domain + " is not a valid domain")
	}
	key = domain + "_" + strconv.Itoa(int(rtype))
	return
}
Exemple #7
0
func updateRecord(r dns.RR, q *dns.Question) {
	if *debug {
		Log.Printf("updateRecord: resource record: %+v, question: %+v\n", r, q)
	}

	var (
		rr    dns.RR
		name  string
		rtype uint16
		ttl   uint32
		ip    net.IP
	)

	header := r.Header()
	name = header.Name
	rtype = header.Rrtype
	ttl = header.Ttl

	if _, ok := dns.IsDomainName(name); ok {
		if header.Class == dns.ClassANY && header.Rdlength == 0 { // Delete record
			deleteRecord(name, rtype)
		} else { // Add record
			rheader := dns.RR_Header{
				Name:   name,
				Rrtype: rtype,
				Class:  dns.ClassINET,
				Ttl:    ttl,
			}

			if a, ok := r.(*dns.A); ok {
				rrr, err := getRecord(name, rtype)
				if err == nil {
					rr = rrr.(*dns.A)
				} else {
					rr = new(dns.A)
				}

				ip = a.A
				rr.(*dns.A).Hdr = rheader
				rr.(*dns.A).A = ip
			} else if a, ok := r.(*dns.AAAA); ok {
				rrr, err := getRecord(name, rtype)
				if err == nil {
					rr = rrr.(*dns.AAAA)
				} else {
					rr = new(dns.AAAA)
				}

				ip = a.AAAA
				rr.(*dns.AAAA).Hdr = rheader
				rr.(*dns.AAAA).AAAA = ip
			}

			storeRecord(rr)
		}
	}
}
func (DT *DomainRRTree) GetDomainNodeFromCacheWithName(d string) (*DomainNode, *MyError.MyError) {
	if _, ok := dns.IsDomainName(d); ok {
		dn := &Domain{
			DomainName: dns.Fqdn(d),
		}
		return DT.GetDomainNodeFromCache(dn)
	}
	return nil, MyError.NewError(MyError.ERROR_PARAM, "Eorror param: "+reflect.ValueOf(d).String())
}
// Preparation for Query A and CNAME / NS record.
// param d 		: domain name to query
// 		isEdns0 : either use edns0_subnet or not
// return :
//		*MyError.Myerror
//		domain name server ip
//		domain name server port
//		*dns.OPT (for edns0_subnet)
func preQuery(d, srcIP string) (*dns.OPT, *MyError.MyError) {
	if _, ok := dns.IsDomainName(d); !ok {
		//		return "", "", nil, MyError.NewError(MyError.ERROR_PARAM, d+" is not a domain name!")
	}

	var o *dns.OPT
	if len(srcIP) > 0 {
		o = PackEdns0SubnetOPT(srcIP, DEFAULT_SOURCEMASK, DEFAULT_SOURCESCOPE)
	} else {
		o = nil
	}
	return o, nil
}
func NewDomainNode(d string, soakey string, t uint32) (*DomainNode, *MyError.MyError) {
	if _, ok := dns.IsDomainName(d); !ok {
		return nil, MyError.NewError(MyError.ERROR_PARAM, d+" is not valid domain name")
	}
	return &DomainNode{
		Domain: Domain{
			DomainName: dns.Fqdn(d),
			SOAKey:     soakey,
			TTL:        t,
		},
		DomainRegionTree: NewDomainRegionTree(),
	}, nil
}
func HttpDispacherQueryServe(w http.ResponseWriter, r *http.Request) {
	url_path := r.URL.Path
	query_domain := r.URL.Query().Get("d")
	srcIP := r.URL.Query().Get("ip")
	if _, ok := dns.IsDomainName(query_domain); !ok {
		fmt.Fprintln(w, "Error domain name: ", query_domain)
		utils.ServerLogger.Info("error domain name : %s ", query_domain)
		return
	}

	if srcIP == "" {
		hp := strings.Split(r.RemoteAddr, ":")
		srcIP = hp[0]
	}
	utils.QueryLogger.Info("src ip: %s query_domain: %s url_path: %s", string(srcIP), query_domain, url_path)
	if x := net.ParseIP(srcIP); x == nil {
		w.WriteHeader(http.StatusForbidden)
		fmt.Fprint(w, srcIP)
		fmt.Fprintln(w, "src ip : "+srcIP+" is not correct")
		utils.ServerLogger.Warning("src ip : %s is not correct", srcIP)
		return
	}

	if config.InWhiteList(query_domain) {
		ok, re, e := query.GetARecord(query_domain, srcIP)
		if ok {
			w.Header().Set("Content-Type", "text/plain")
			w.WriteHeader(http.StatusOK)
			for _, ree := range re {
				if a, ok := ree.(*dns.A); ok {
					fmt.Fprintln(w, a.A.String())
					utils.ServerLogger.Debug("query result: %s ", a.A.String())
				} else {
					fmt.Fprintln(w, ree.String())
					utils.ServerLogger.Debug("query result: %s ", ree.String())
				}
			}
		} else if e != nil {
			fmt.Fprintln(w, e.Error())
			utils.ServerLogger.Error("query domain: %s src_ip: %s  %s", query_domain, srcIP, e.Error())
		} else {
			fmt.Fprintln(w, "unkown error!\n")
			utils.ServerLogger.Error("query domain: %s src_ip: %s fail unkown error!", query_domain, srcIP)
		}
	} else {
		w.WriteHeader(http.StatusForbidden)
		fmt.Fprintln(w, "Query for domain: "+query_domain+" is not permited\n")
		utils.ServerLogger.Info("Query for domain: %s is not permited", query_domain)
		return
	}
}
Exemple #12
0
func NewDNSTransportUpstreamCodec(domain string) (*DNSTransportUpstreamCodec, error) {
	ret := DNSTransportUpstreamCodec{domain: domain + "."}
	var ok bool
	if ret.domain_label_count, ok = dns.IsDomainName(ret.domain); !ok {
		return nil, fmt.Errorf("Bad domain %d", domain)
	}
	name_len := 255 - len(ret.domain)
	name_len -= 9 // seq number (4 byte --base32--> 8byte) + '.'

	ret.max_len_per_name = name_len / 64 * DNS_UPSTREAM_MAX_LEN_PER_LABEL
	if tmp := name_len % 64; tmp > 9 {
		ret.max_len_per_name += (tmp - 1) / 8 * 5
	}
	ret.header_codec = bitcodec.NewBitcodec(&DNSCodecHeader{})

	return &ret, nil
}
Exemple #13
0
// Handler for DNS queries
func query(w http.ResponseWriter, r *http.Request) {
	server := r.URL.Query().Get(":server")
	domain := dns.Fqdn(r.URL.Query().Get(":domain"))
	querytype := r.URL.Query().Get(":querytype")

	if domain, err := idna.ToASCII(domain); err == nil { // Valid domain name (ASCII or IDN)
		if _, isDomain := dns.IsDomainName(domain); isDomain { // Well-formed domain name
			if querytype, ok := dns.StringToType[strings.ToUpper(querytype)]; ok { // Valid DNS query type
				resolve(w, r, server, domain, querytype)
			} else {
				error(w, 400, 404, "Invalid DNS query type")
			}
		} else {
			error(w, 400, 402, "Input string is not a well-formed domain name")
		}
	} else {
		error(w, 400, 401, "Input string could not be parsed")
	}
}
func (DT *DomainRRTree) UpdateDomainNode(d *DomainNode) (bool, *MyError.MyError) {
	if _, ok := dns.IsDomainName(d.DomainName); ok {
		if dt, err := DT.GetDomainNodeFromCache(&d.Domain); dt != nil && err == nil {
			d.DomainRegionTree = dt.DomainRegionTree
			DT.RWMutex.Lock()
			r := DT.LLRB.ReplaceOrInsert(d)
			DT.RWMutex.Unlock()
			if r != nil {
				return true, nil

			} else {
				//Exception:see source code of "LLRB.ReplaceOrInsert"
				return true, MyError.NewError(MyError.ERROR_UNKNOWN, "Update error, but inserted")
			}
		} else {
			return false, MyError.NewError(MyError.ERROR_NOTFOUND, "DomainRRTree does not has "+reflect.ValueOf(d).String()+" or it has "+reflect.ValueOf(dt).String())
		}
	} else {
		return false, MyError.NewError(MyError.ERROR_PARAM, " Param d "+reflect.ValueOf(d).String()+" is not valid Domain instance")
	}
	return false, MyError.NewError(MyError.ERROR_UNKNOWN, "UpdateDomainNode return unknown error")
}
Exemple #15
0
func (dom Domain) addHandler(tld string) {
	fqdn := dom.Name
	if tld != "" {
		fqdn = dom.Name + "." + tld
	}

	FqdnParts, _ := dns.IsDomainName(fqdn)

	fmt.Printf("Adding: %v - %v nums\n", fqdn, FqdnParts)

	// Handle dns requests if it is really a fqdn
	if dns.IsFqdn(fqdn) {
		dns.HandleFunc(fqdn, func(w dns.ResponseWriter, req *dns.Msg) {
			m := new(dns.Msg)
			m.SetReply(req)
			m.Compress = true

			for i, q := range req.Question {
				fmt.Printf("Requested: %s, Type: %v\n", req.Question[i].Name, req.Question[i].Qtype)

				switch q.Qtype {
				case 1:
					fmt.Printf("Adding a record %v with ip %v", q.Name, dom.A.Ip)
					m.Answer = append(m.Answer, NewA(q.Name, dom.A.Ip, uint32(dom.A.Ttl)))
				case 15:
					fmt.Printf("Adding a record %v with ip %v", q.Name, dom.A.Ip)
					m.Answer = append(m.Answer, NewMX(q.Name, dom.Mx.Content, dom.Mx.Priority, uint32(dom.Mx.Ttl)))
				}
			}

			w.WriteMsg(m)
		})
	}

	// add subdomains..
	for _, d := range dom.Domains {
		d.addHandler(fqdn)
	}
}
Exemple #16
0
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 ""
}
Exemple #17
0
func validateStaticEntryFile(sef string) (StaticEntryConfig, error) {
	if len(sef) == 0 {
		return StaticEntryConfig{}, nil
	}

	if _, err := os.Stat(sef); os.IsNotExist(err) {
		return StaticEntryConfig{}, fmt.Errorf("StaticEntryFile not found: %s", sef)
	}

	conf, err := ParseStaticConfig(sef)

	for _, entry := range conf.Entries {
		switch entry.Type {
		case "A":
			ip := net.ParseIP(entry.Value)
			if ip == nil {
				return conf, fmt.Errorf("Invalid IP on StaticEntry: %q", entry.Value)
			}
			if !dns.IsFqdn(entry.Fqdn) {
				return conf, fmt.Errorf("Invalid FQDN: %s", entry.Fqdn)
			}
			break
		case "SRV":
			if _, ok := dns.IsDomainName(entry.Fqdn); !ok {
				return conf, fmt.Errorf("Invalid SRV FQDN: %s", entry.Fqdn)
			}
			if match, _ := regexp.MatchString(ValidHostPortRegex, entry.Value); !match {
				return conf, fmt.Errorf("Invalid (Host:Port) tuple: %s", entry.Value)
			}
			break
		default:
			return conf, fmt.Errorf("Unsupported Record Type: %s", entry.Type)
		}
	}

	return conf, err
}
Exemple #18
0
		rr = &dns.TXT{header, []string{node.Value}}
		return
	},

	dns.TypeCNAME: func(node *etcd.Node, header dns.RR_Header) (rr dns.RR, err error) {
		rr = &dns.CNAME{header, dns.Fqdn(node.Value)}
		return
	},

	dns.TypeNS: func(node *etcd.Node, header dns.RR_Header) (rr dns.RR, err error) {
		rr = &dns.NS{header, dns.Fqdn(node.Value)}
		return
	},

	dns.TypePTR: func(node *etcd.Node, header dns.RR_Header) (rr dns.RR, err error) {
		labels, ok := dns.IsDomainName(node.Value)

		if ok && labels > 0 {
			rr = &dns.PTR{header, dns.Fqdn(node.Value)}
		} else {
			err = &NodeConversionError{
				Node:          node,
				Message:       fmt.Sprintf("Value '%s' isn't a valid domain name", node.Value),
				AttemptedType: dns.TypePTR}
		}
		return
	},

	dns.TypeSRV: func(node *etcd.Node, header dns.RR_Header) (rr dns.RR, err error) {
		parts := strings.SplitN(node.Value, "\t", 4)
func QuerySOA(d string) (*dns.SOA, []*dns.NS, *MyError.MyError) {
	//fmt.Println(utils.GetDebugLine(), " QuerySOA: ", d)
	utils.ServerLogger.Debug(" QuerySOA domain: %s ", d)
	if _, ok := dns.IsDomainName(d); !ok {
		return nil, nil, MyError.NewError(MyError.ERROR_PARAM, d+" is not a domain name")
	}
	cf, el := dns.ClientConfigFromFile("/etc/resolv.conf")
	if el != nil {
		return nil, nil, MyError.NewError(MyError.ERROR_UNKNOWN, "Get dns config from file /etc/resolv.conf failed")
	}

	var soa *dns.SOA
	var ns_a []*dns.NS
	for c := 0; (soa == nil) && (c < 3); c++ {

		soa, ns_a = nil, nil
		r, e := DoQuery(d, cf.Servers, cf.Port, dns.TypeSOA, nil, UDP)
		//		fmt.Println(r)
		if e != nil {
			utils.QueryLogger.Error("QeurySOA got error : "+e.Error()+
				". Param: %s , %v, %s, %v ", d, cf.Servers, cf.Port, dns.TypeSOA)
			continue
		} else {
			var rr []dns.RR
			if r.Answer != nil {
				rr = append(rr, r.Answer...)
			}
			if r.Ns != nil {
				rr = append(rr, r.Ns...)
			}
			soa, ns_a, e = ParseSOA(d, rr)
			if e != nil {
				switch e.ErrorNo {
				case MyError.ERROR_SUBDOMAIN, MyError.ERROR_NOTVALID:
					utils.ServerLogger.Error("ERROR_NOTVALID: %s", e.Error())
					var ee *MyError.MyError
					d, ee = GenerateParentDomain(d)
					if ee != nil {
						if ee.ErrorNo == MyError.ERROR_NORESULT {
							//							fmt.Println(ee)
							//							continue
						}
						return nil, nil, MyError.NewError(MyError.ERROR_NORESULT,
							d+" has no SOA record "+" because of "+ee.Error())
					}
					continue
				case MyError.ERROR_NORESULT:
					//					c++
					//fmt.Println(utils.GetDebugLine(), e)
					utils.ServerLogger.Error("ERROR_NORESULT: %s", e.Error())
					//fmt.Println("+++++++++++++++++++++++++++++++++++")
					continue
				default:
					//					c++
					utils.ServerLogger.Error("ERROR_DEFAULT: %s", e.Error())
					//fmt.Println(utils.GetDebugLine(), ".....................")
					//fmt.Println(utils.GetDebugLine(), e)
					continue
					//					return nil, nil, e
				}
			} else {
				if cap(ns_a) < 1 {
					//fmt.Println(utils.GetDebugLine(), "QuerySOA: line 223: cap(ns_a)<1, need QueryNS ", soa.Hdr.Name)
					utils.ServerLogger.Debug("QuerySOA: cap(ns_a)<1, need QueryNS: %s", soa.Hdr.Name)
					ns_a, e = QueryNS(soa.Hdr.Name)
					if e != nil {
						//TODO: do some log
					}
				}
				//				fmt.Println("============xxxxxx================")
				//fmt.Println(utils.GetDebugLine(), "QuerySOA: soa record ", soa, " ns_a: ", ns_a)
				utils.ServerLogger.Debug("QuerySOA: soa record %v ns_a: %v", soa, ns_a)
				return soa, ns_a, nil
			}
		}
	}
	return nil, nil, MyError.NewError(MyError.ERROR_UNKNOWN, d+" QuerySOA faild with unknow error")
}