Example #1
0
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
}
Example #2
0
// 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
	}
}
Example #3
0
func answerAAAA(msg *dns.Msg, question dns.Question, name []string, value NMCValue) {
	var parsedIp net.IP
	// len == 1 means root domain: check "ip" and "map".""
	if len(name) == 1 {
		vips := value.Ip6

		if len(vips) == 0 {
			// can't answer, make an error here.
			return
		} else {
			parsedIp = net.ParseIP(vips[0])
		}
	}

	ip := parsedIp.To16()
	if ip == nil {
		return
	}

	LOG.Println("AAAA", name, "=>", ip)

	rraaaa := &dns.RR_AAAA{}
	copy(ip, rraaaa.AAAA[:])

	rrh := &dns.RR_Header{
		Name:     question.Name,
		Rrtype:   dns.TypeAAAA,
		Class:    dns.ClassINET,
		Ttl:      60,
		Rdlength: 100,
	}
	rraaaa.Hdr = *rrh

	msg.Rcode = dns.RcodeSuccess
	msg.Answer = append(msg.Answer, rraaaa)
	msg.Response = true
	msg.Authoritative = true
	msg.Recursion_desired = true
	msg.Recursion_available = true
}
Example #4
0
func answerA(msg *dns.Msg, question dns.Question, name []string, value NMCValue) {
	var parsedIp net.IP
	// len == 1 means root domain: check "ip" and "map".""
	if len(name) == 1 {
		vips := value.Ip

		// this is legacy support
		if len(vips) == 0 {
			vmap := value.Map
			if vmap == nil {
				return
			}

			vmip, ok := value.Map[""]
			if !ok && vmip == "" {
				// can't answer, make an error here.
				return
			}

			switch vmip.(type) {
			case nil:
				return
			case map[string]interface{}:
				nsAvailable := vmip.(map[string]interface{})["ns"]

				switch nsAvailable.(type) {
				case []interface{}:
					ns := nsAvailable.([]interface{})[0]

					switch ns.(type) {
					case string:
						h := dns.MsgHdr{
							Id:                uint16(rand.Int()) ^ uint16(time.Nanoseconds()),
							Recursion_desired: true,
						}

						q := &dns.Question{
							Name:   question.Name,
							Qtype:  dns.TypeA,
							Qclass: dns.ClassINET,
						}

						m := &dns.Msg{}
						m.MsgHdr = h
						m.Question = append(m.Question, *q)

						LOG.Println(m)

						out, ok := m.Pack()
						if !ok {
							LOG.Fatalln("Failed to Pack:", msg)
						}

						nsaddr := ns.(string) + ":53"
						conn, err := net.Dial("udp", nsaddr)
						if err != nil {
							LOG.Fatalf("net.DialUDP(\"udp\", nil, %v) => %v", nsaddr, err)
						}
						LOG.Println("out:", out)

						n, err := conn.Write(out)
						if err != nil {
							LOG.Fatalln(err)
						}
						LOG.Println("wrote:", n)

						conn.SetReadTimeout(10e9)
						defer conn.Close()

						b := make([]byte, 1<<15)
						s, err := conn.Read(b)
						if err != nil {
							LOG.Fatalln(err, nsaddr)
						}

						err = conn.Close()
						if err != nil {
							LOG.Fatalln(err)
						}

						a := &dns.Msg{}
						a.Unpack(b[0:s])

						LOG.Println("a:", a)

						msg.Answer = append(msg.Answer, a.Answer[0])
						return
					default:
						LOG.Printf("can't find the type of: %#v", ns)
					}
				default:
					LOG.Printf("can't find the type of: %#v", nsAvailable)
				}
			case string:
				parsedIp = net.ParseIP(vmip.(string))
			default:
				LOG.Printf("can't find the type of: %#v", vmip)
			}

		} else {
			parsedIp = net.ParseIP(vips[0])
		}
	}

	ip := parsedIp.To4()
	if ip == nil {
		return
	}

	LOG.Println("A", name, "=>", ip)

	var a uint32
	rra := &dns.RR_A{}
	rra.A = (a | uint32(ip[0])<<24 | uint32(ip[1])<<16 | uint32(ip[2])<<8 | uint32(ip[3]))

	rrh := &dns.RR_Header{
		Name:     question.Name,
		Rrtype:   dns.TypeA,
		Class:    dns.ClassINET,
		Ttl:      60,
		Rdlength: 100,
	}
	rra.Hdr = *rrh

	msg.Rcode = dns.RcodeSuccess
	msg.Answer = append(msg.Answer, rra)
	msg.Response = true
	msg.Authoritative = true
	msg.Recursion_desired = true
	msg.Recursion_available = true
}