예제 #1
0
파일: client.go 프로젝트: Gaboose/mdns
// recv is used to receive until we get a shutdown
func (c *client) recv(l *net.UDPConn, msgCh chan *dns.Msg) {
	if l == nil {
		return
	}
	buf := make([]byte, 65536)

	var closed bool
	for {
		c.closeLock.RLock()
		closed = c.closed
		c.closeLock.RUnlock()
		if closed {
			break
		}
		n, err := l.Read(buf)
		if err != nil {
			Log.Printf("[ERR] mdns: Failed to read packet: %v", err)
			continue
		}
		msg := new(dns.Msg)
		if err := msg.Unpack(buf[:n]); err != nil {
			Log.Printf("[ERR] mdns: Failed to unpack packet: %v", err)
			continue
		}
		select {
		case msgCh <- msg:
		case <-c.closedCh:
			return
		}
	}
}
예제 #2
0
func ParseDnsFrame(f Frame, req *dns.Msg) (addrs []net.IP, err error) {
	ft, ok := f.(*FrameDns)
	if !ok {
		return nil, ErrDnsMsgIllegal
	}

	res := new(dns.Msg)
	err = res.Unpack(ft.Data)
	if err != nil || !res.Response || res.Id != req.Id {
		return nil, ErrDnsMsgIllegal
	}

	if DEBUGDNS {
		DebugDNS(res, req.Question[0].Name)
	}
	for _, a := range res.Answer {
		switch ta := a.(type) {
		case *dns.A:
			addrs = append(addrs, ta.A)
		case *dns.AAAA:
			addrs = append(addrs, ta.AAAA)
		}
	}
	return
}
예제 #3
0
func TestTCP(t *testing.T) {
	handle, err := pcap.OpenOffline("tcptest.pcap")
	if err != nil {
		panic(err)
	}
	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
	defer handle.Close()
	tcpPack := make(chan gopacket.Packet, 10)
	nomalPack := make(chan gopacket.Packet, 5)
	for input_pack := range packetSource.Packets() { // send tcp package for channel
		tcpLayer := input_pack.Layer(layers.LayerTypeTCP)
		if tcpLayer != nil {
			tcpPack <- input_pack
			// send packet to tcp ASSEMBLER
		}
	}
	streamFactory := &DNSStreamFactory{normal: nomalPack}
	streamPool := tcpassembly.NewStreamPool(streamFactory)
	assembler := tcpassembly.NewAssembler(streamPool)
	go tcpAssemble(tcpPack, assembler)
	pack := <-nomalPack
	udpLayer := pack.Layer(layers.LayerTypeUDP)
	if udpLayer == nil {
		t.Errorf("can not fine udp Layer in result")
	}
	dns_message := new(dns.Msg)
	err = dns_message.Unpack(udpLayer.LayerPayload())
	if err != nil {
		t.Errorf("can not parse dns message")
	}
	fmt.Printf(dns_message.String())
}
예제 #4
0
파일: server.go 프로젝트: edc1591/gohome
// parsePacket is used to parse an incoming packet
func (s *Server) parsePacket(packet []byte, from net.Addr) error {
	var msg dns.Msg
	if err := msg.Unpack(packet); err != nil {
		log.Printf("[ERR] bonjour: Failed to unpack packet: %v", err)
		return err
	}
	return s.handleQuery(&msg, from)
}
예제 #5
0
파일: dns.go 프로젝트: yinqiwen/gsnova
func dnsQueryRaw(r []byte) ([]byte, error) {
	req := new(dns.Msg)
	req.Unpack(r)
	res, err := dnsQuery(req)
	if nil != err {
		return nil, err
	}
	return res.Pack()
}
예제 #6
0
func safeParse(msg *dns.Msg, data []byte) (err error) {
	defer func() {
		if e := recover(); e != nil {
			fmt.Fprintf(os.Stderr, "Crashed dns: %v\nError: %v\n",
				hex.EncodeToString(data), e)
			err = fmt.Errorf("bad packet")
		}
	}()
	return msg.Unpack(data)
}
예제 #7
0
func TestRFC2136ValidUpdatePacket(t *testing.T) {
	dns.HandleFunc(rfc2136TestZone, serverHandlerPassBackRequest)
	defer dns.HandleRemove(rfc2136TestZone)

	server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
	if err != nil {
		t.Fatalf("Failed to start test server: %v", err)
	}
	defer server.Shutdown()

	rr := new(dns.TXT)
	rr.Hdr = dns.RR_Header{
		Name:   rfc2136TestFqdn,
		Rrtype: dns.TypeTXT,
		Class:  dns.ClassINET,
		Ttl:    uint32(rfc2136TestTTL),
	}
	rr.Txt = []string{rfc2136TestValue}
	rrs := make([]dns.RR, 1)
	rrs[0] = rr
	m := new(dns.Msg)
	m.SetUpdate(dns.Fqdn(rfc2136TestZone))
	m.Insert(rrs)
	expectstr := m.String()
	expect, err := m.Pack()
	if err != nil {
		t.Fatalf("Error packing expect msg: %v", err)
	}

	provider, err := NewDNSProviderRFC2136(addrstr, rfc2136TestZone, "", "")
	if err != nil {
		t.Fatalf("Expected NewDNSProviderRFC2136() to return no error but the error was -> %v", err)
	}

	if err := provider.Present(rfc2136TestDomain, "", "1234d=="); err != nil {
		t.Errorf("Expected Present() to return no error but the error was -> %v", err)
	}

	rcvMsg := <-reqChan
	rcvMsg.Id = m.Id
	actual, err := rcvMsg.Pack()
	if err != nil {
		t.Fatalf("Error packing actual msg: %v", err)
	}

	if !bytes.Equal(actual, expect) {
		tmp := new(dns.Msg)
		if err := tmp.Unpack(actual); err != nil {
			t.Fatalf("Error unpacking actual msg: %v", err)
		}
		t.Errorf("Expected msg:\n%s", expectstr)
		t.Errorf("Actual msg:\n%v", tmp)
	}
}
예제 #8
0
func safeParse(msg *dns.Msg, data []byte) (err error) {
	defer func() {
		if e := recover(); e != nil {
			hexs := hex.EncodeToString(data)
			fmt.Fprintf(os.Stderr, "Crashed dns: %v\nError: %v\n",
				hexs, e)
			panic("Unpacking dns crashed: " + hexs)
		}
	}()
	return msg.Unpack(data)
}
예제 #9
0
파일: mdns.go 프로젝트: davecheney/mdns
// consume an mdns packet from the wire and decode it
func (c *connector) readMessage() (*dns.Msg, *net.UDPAddr, error) {
	buf := make([]byte, 1500)
	read, addr, err := c.ReadFromUDP(buf)
	if err != nil {
		return nil, nil, err
	}
	var msg dns.Msg
	if err := msg.Unpack(buf[:read]); err != nil {
		return nil, nil, err
	}
	return &msg, addr, nil
}
예제 #10
0
func (conn *DNSUDPConn) ReadDNSFromUDP() (*dns.Msg, *net.UDPAddr, error) {
	buf := make([]byte, DNS_MAX_UDP_SIZE)
	rdlen, addr, err := conn.ReadFromUDP(buf)
	if rdlen == 0 || err != nil {
		return nil, nil, fmt.Errorf("Error reading from UDP: %v", err)
	}
	m := new(dns.Msg)
	if err = m.Unpack(buf[:rdlen]); err != nil {
		return nil, nil, err
	}
	return m, addr, nil
}
예제 #11
0
파일: mdns.go 프로젝트: zserge/mdns
// A loop that reads incoming mDNS questions from UDP connection
// and passes them into the main loop question channel
func (m *mdns) readloop(c *net.UDPConn, in chan msg) {
	buf := make([]byte, 1500)
	for {
		if n, addr, err := c.ReadFromUDP(buf); err != nil {
			return
		} else {
			var dnsmsg dns.Msg
			if err := dnsmsg.Unpack(buf[:n]); err == nil {
				in <- msg{&dnsmsg, addr, c}
			}
		}
	}
}
예제 #12
0
파일: main.go 프로젝트: soh335/go-mdns
func (c *Client) readUDP() (*net.UDPAddr, *dns.Msg, error) {
	in := make([]byte, dns.DefaultMsgSize)
	read, addr, err := c.conn.ReadFromUDP(in)
	if err != nil {
		return nil, nil, err
	}

	var readMsg dns.Msg
	if err := readMsg.Unpack(in[:read]); err != nil {
		return nil, nil, err
	}

	return addr, &readMsg, nil
}
예제 #13
0
func TestRFC2136ValidUpdatePacket(t *testing.T) {
	acme.ClearFqdnCache()
	dns.HandleFunc(rfc2136TestZone, serverHandlerPassBackRequest)
	defer dns.HandleRemove(rfc2136TestZone)

	server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
	if err != nil {
		t.Fatalf("Failed to start test server: %v", err)
	}
	defer server.Shutdown()

	txtRR, _ := dns.NewRR(fmt.Sprintf("%s %d IN TXT %s", rfc2136TestFqdn, rfc2136TestTTL, rfc2136TestValue))
	rrs := []dns.RR{txtRR}
	m := new(dns.Msg)
	m.SetUpdate(rfc2136TestZone)
	m.RemoveRRset(rrs)
	m.Insert(rrs)
	expectstr := m.String()
	expect, err := m.Pack()
	if err != nil {
		t.Fatalf("Error packing expect msg: %v", err)
	}

	provider, err := NewDNSProvider(addrstr, "", "", "")
	if err != nil {
		t.Fatalf("Expected NewDNSProvider() to return no error but the error was -> %v", err)
	}

	if err := provider.Present(rfc2136TestDomain, "", "1234d=="); err != nil {
		t.Errorf("Expected Present() to return no error but the error was -> %v", err)
	}

	rcvMsg := <-reqChan
	rcvMsg.Id = m.Id
	actual, err := rcvMsg.Pack()
	if err != nil {
		t.Fatalf("Error packing actual msg: %v", err)
	}

	if !bytes.Equal(actual, expect) {
		tmp := new(dns.Msg)
		if err := tmp.Unpack(actual); err != nil {
			t.Fatalf("Error unpacking actual msg: %v", err)
		}
		t.Errorf("Expected msg:\n%s", expectstr)
		t.Errorf("Actual msg:\n%v", tmp)
	}
}
예제 #14
0
파일: cache.go 프로젝트: d2g/cloudpathway
func (this *cache) Get(message *dns.Msg) (bool, *dns.Msg, error) {
	cachedMessage := CacheRecord{}
	err := this.collection.GetObject(message.Question[0].Name, &cachedMessage)
	if err != nil {
		return false, nil, err
	}

	cachedMessageMsg := dns.Msg{}
	err = cachedMessageMsg.Unpack(cachedMessage.Record)
	if err != nil {
		return false, nil, err
	}

	if cachedMessageMsg.Id != 0 && cachedMessage.Expiry.After(time.Now()) {
		return true, &cachedMessageMsg, nil
	} else {
		return false, &dns.Msg{}, nil
	}
}
예제 #15
0
// @Private
func (this *UDPNameServer) HandleResponse(dest v2net.Destination, payload *alloc.Buffer) {
	msg := new(dns.Msg)
	err := msg.Unpack(payload.Value)
	if err != nil {
		log.Warning("DNS: Failed to parse DNS response: ", err)
		return
	}
	record := &ARecord{
		IPs: make([]net.IP, 0, 16),
	}
	id := msg.Id
	ttl := DefaultTTL
	log.Debug("DNS: Handling response for id ", id, " content: ", msg.String())

	this.Lock()
	request, found := this.requests[id]
	if !found {
		this.Unlock()
		return
	}
	delete(this.requests, id)
	this.Unlock()

	for _, rr := range msg.Answer {
		switch rr := rr.(type) {
		case *dns.A:
			record.IPs = append(record.IPs, rr.A)
			if rr.Hdr.Ttl < ttl {
				ttl = rr.Hdr.Ttl
			}
		case *dns.AAAA:
			record.IPs = append(record.IPs, rr.AAAA)
			if rr.Hdr.Ttl < ttl {
				ttl = rr.Hdr.Ttl
			}
		}
	}
	record.Expire = time.Now().Add(time.Second * time.Duration(ttl))

	request.response <- record
	close(request.response)
}
예제 #16
0
func (c *dnsCache) store(payload []byte) {
	resp := new(dns.Msg)
	e := resp.Unpack(payload)
	if e != nil {
		return
	}
	if resp.Rcode != dns.RcodeSuccess {
		return
	}
	if len(resp.Question) == 0 || len(resp.Answer) == 0 {
		return
	}

	c.mutex.Lock()
	defer c.mutex.Unlock()
	c.storage[cacheKey(resp.Question[0])] = &dnsCacheEntry{
		msg: resp,
		exp: time.Now().Add(time.Duration(resp.Answer[0].Header().Ttl) * time.Second),
	}
}
예제 #17
0
func (s *Session) on_dns(ft *FrameDns) (err error) {
	req := new(dns.Msg)
	err = req.Unpack(ft.Data)
	if err != nil {
		return ErrDnsMsgIllegal
	}

	if req.Response {
		// ignore send fail, maybe just timeout.
		// should I log this ?
		return s.sendFrameInChan(ft)
	}

	log.Info("dns query for %s.", req.Question[0].Name)

	d, ok := sutils.DefaultLookuper.(*sutils.DnsLookup)
	if !ok {
		return ErrNoDnsServer
	}
	res, err := d.Exchange(req)
	if err != nil {
		log.Error("%s", err.Error())
		return nil
	}

	if DEBUGDNS {
		DebugDNS(res, req.Question[0].Name)
	}

	// send response back from streamid
	b, err := res.Pack()
	if err != nil {
		log.Error("%s", ErrDnsMsgIllegal.Error())
		return nil
	}

	fr := NewFrameDns(ft.GetStreamid(), b)
	err = s.SendFrame(fr)
	return
}
예제 #18
0
파일: client.go 프로젝트: brutella/hklifx
// Data receiving routine reads from connection, unpacks packets into dns.Msg
// structures and sends them to a given msgCh channel
func (c *client) recv(l *net.UDPConn, msgCh chan *dns.Msg) {
	if l == nil {
		return
	}
	buf := make([]byte, 65536)
	for !c.closed {
		n, _, err := l.ReadFrom(buf)
		if err != nil {
			continue
		}
		msg := new(dns.Msg)
		if err := msg.Unpack(buf[:n]); err != nil {
			log.Printf("[ERR] mdns: Failed to unpack packet: %v", err)
			continue
		}
		select {
		case msgCh <- msg:
		case <-c.closedCh:
			return
		}
	}
}
예제 #19
0
func (c *dnsCache) query(payload []byte) *dns.Msg {
	request := new(dns.Msg)
	e := request.Unpack(payload)
	if e != nil {
		return nil
	}
	if len(request.Question) == 0 {
		return nil
	}

	c.mutex.Lock()
	defer c.mutex.Unlock()
	key := cacheKey(request.Question[0])
	entry := c.storage[key]
	if entry == nil {
		return nil
	}
	if time.Now().After(entry.exp) {
		delete(c.storage, key)
		return nil
	}
	entry.msg.Id = request.Id
	return entry.msg
}
예제 #20
0
func (this Server) tryDNSoverHTTP(w http.ResponseWriter, r *http.Request) {
	TransProString := r.Header.Get("Proxy-DNS-Transport")
	if TransProString == "" {
		TransProString = r.Header.Get("X-Proxy-DNS-Transport")
	}
	if TransProString == "" {
		msg := fmt.Sprintf("No transport protocol specified")
		_D("%s", msg)
		http.Error(w, msg, 415)
		return
	}
	if TransProString == "TCP" {
		this.TransPro = TCPcode
	} else if TransProString == "UDP" {
		this.TransPro = UDPcode
	} else {
		msg := fmt.Sprintf("Transport protocol not UDP or TCP: %s", TransProString)
		_D("%s", msg)
		http.Error(w, msg, 415)
		return
	}
	contentTypeStr := r.Header.Get("Content-Type")
	if contentTypeStr != "application/octet-stream" {
		msg := fmt.Sprintf("Unsupported content-type: '%s'", contentTypeStr)
		_D("%s", msg)
		http.Error(w, msg, 415)
		return
	}
	var requestBody []byte
	requestBody, err := ioutil.ReadAll(r.Body)
	if err != nil {
		msg := fmt.Sprintf("Error reading HTTP request: %s", err)
		_D("%s", msg)
		http.Error(w, msg, 400)
		return
	}
	if len(requestBody) < (int)(r.ContentLength) {
		msg := fmt.Sprintf("Error reading HTTP request: expected %d bytes but only read %d",
			(int)(r.ContentLength), len(requestBody))
		_D("%s", msg)
		http.Error(w, msg, 400)
		return
	}
	var dnsRequest dns.Msg
	err = dnsRequest.Unpack(requestBody)
	if err != nil {
		msg := fmt.Sprintf("Error unpacking DNS message: %s", err)
		_D("%s", msg)
		http.Error(w, msg, 400)
		return
	}
	dnsResponse, err := DoDNSquery(dnsRequest, TransProString, this.SERVERS, this.timeout)
	if err != nil {
		msg := fmt.Sprintf("Error querying DNS resolver: %s", err)
		_D("%s", msg)
		http.Error(w, msg, 500)
		return
	}
	if dnsResponse == nil {
		msg := "Error querying DNS resolver: no response"
		_D("%s", msg)
		http.Error(w, msg, 500)
		return
	}
	response_bytes, err := dnsResponse.Pack()
	if err != nil {
		msg := fmt.Sprintf("Error converting DNS message to bytes: %s", err)
		_D("%s", msg)
		http.Error(w, msg, 500)
		return
	}
	_, err = w.Write(response_bytes)
	if err != nil {
		msg := fmt.Sprintf("Error writing HTTP response: %s", err)
		_D("%s", msg)
		return
	}
}
예제 #21
0
func (w *Writer) Write(b []byte) (i int, err error) {
	r := new(dns.Msg)
	err = r.Unpack(b)
	w.ReplyCh <- r
	return
}
예제 #22
0
func proxyServe(w dns.ResponseWriter, req *dns.Msg) {
	var (
		key       string
		m         *dns.Msg
		err       error
		tried     bool
		data      []byte
		id        uint16
		query     []string
		questions []dns.Question
		used      string
	)

	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		}
	}()

	if req.MsgHdr.Response == true { // supposed responses sent to us are bogus
		return
	}

	query = make([]string, len(req.Question))

	for i, q := range req.Question {
		if q.Qtype != dns.TypeAAAA || *ipv6 {
			questions = append(questions, q)
		}
		query[i] = fmt.Sprintf("(%s %s %s)", q.Name, dns.ClassToString[q.Qclass], dns.TypeToString[q.Qtype])
	}

	if len(questions) == 0 {
		return
	}

	req.Question = questions

	id = req.Id

	req.Id = 0
	key = toMd5(req.String())
	req.Id = id

	if ENCACHE {
		if reply, ok := conn.Get(key); ok {
			data, _ = reply.([]byte)
		}
		if data != nil && len(data) > 0 {
			m = &dns.Msg{}
			m.Unpack(data)
			m.Id = id
			err = w.WriteMsg(m)

			if DEBUG > 0 {
				log.Printf("id: %5d cache: HIT %v\n", id, query)
			}

			goto end
		} else {
			if DEBUG > 0 {
				log.Printf("id: %5d cache: MISS %v\n", id, query)
			}
		}
	}

	for i, parts := range DNS {
		dns := parts[0]
		proto := parts[1]
		tried = i > 0
		if DEBUG > 0 {
			if tried {
				log.Printf("id: %5d try: %v %s %s\n", id, query, dns, proto)
			} else {
				log.Printf("id: %5d resolve: %v %s %s\n", id, query, dns, proto)
			}
		}
		client := clientUDP
		if proto == "tcp" {
			client = clientTCP
		}
		m, _, err = client.Exchange(req, dns)
		if err == nil && len(m.Answer) > 0 {
			used = dns
			break
		}
	}

	if err == nil {
		if DEBUG > 0 {
			if tried {
				if len(m.Answer) == 0 {
					log.Printf("id: %5d failed: %v\n", id, query)
				} else {
					log.Printf("id: %5d bingo: %v %s\n", id, query, used)
				}
			}
		}
		data, err = m.Pack()
		if err == nil {
			_, err = w.Write(data)

			if err == nil {
				if ENCACHE {
					m.Id = 0
					data, _ = m.Pack()
					ttl := 0
					if len(m.Answer) > 0 {
						ttl = int(m.Answer[0].Header().Ttl)
						if ttl < 0 {
							ttl = 0
						}
					}
					conn.Set(key, data, time.Second*time.Duration(ttl))
					m.Id = id
					if DEBUG > 0 {
						log.Printf("id: %5d cache: CACHED %v TTL %v\n", id, query, ttl)
					}
				}
			}
		}
	}

end:
	if DEBUG > 1 {
		fmt.Println(req)
		if m != nil {
			fmt.Println(m)
		}
	}
	if err != nil {
		log.Printf("id: %5d error: %v %s\n", id, query, err)
	}

	if DEBUG > 1 {
		fmt.Println("====================================================")
	}
}
예제 #23
0
func dnschanDnsQuery(servers map[net.UDPAddr]*dnsServer, domain string, RecordChan chan *DnsRecord, ExitChan chan int) {
	select {
	case <-ExitChan:
		return
	default:
	}
	myexitChan := make(chan int)
	defer func() { close(myexitChan) }()

	// 打开端口
	conn, err := net.ListenUDP("udp", nil)
	if err != nil {
		log.Printf("为dns请求打开udp失败,%v", err)
		return
	}
	defer conn.Close()

	conn.SetDeadline(time.Now().Add(5 * time.Second))

	// dns 请求
	m := new(dns.Msg)
	m.SetQuestion(dns.Fqdn(domain), dns.TypeA)
	m.RecursionDesired = true
	mData, err := m.Pack()
	if err != nil {
		log.Printf("生成dns请求包失败,%v", err)
		return
	}

	// 另开一个线程发出查询
	go func() {
		for k, _ := range servers {
			if _, err := conn.WriteToUDP(mData, k); err != nil {
				log.Printf("向%v发送dns请求失败,%v", k, err)
			}
		}
	}()

	// 等待关闭
	go func() {
		select {
		case <-ExitChan:
		case <-myexitChan:
		}
		conn.Close()
	}()

	// 接收查询结果并输入到信道
	buf := make([]byte, 1500)
	for {
		n, addr, err := conn.ReadFromUDP(buf)
		if err != nil {
			return
		}
		nbuf := buf[:n]

		r := new(dns.Msg)
		if err := r.Unpack(nbuf); err != nil {
			log.Printf("解 DNS 包失败,%v", err)
			continue
		}

		if r.Id != m.Id {
			log.Printf("错误的dns id。")
			continue
		}

		v := servers[*addr]
		if v == nil {
			log.Printf("未知的服务器 %v 回应,忽略。", *addr)
			continue
		}

		for _, a := range r.Answer {
			dnsA, err := a.(*dns.A)
			if err != nil || dnsA == nil {
				log.Printf("内部错误,a=%v,err=%v", dnsA, err)
			}
			select {
			case RecordChan <- &DnsRecord{
				Ip:     dnsA.A.String(),
				Credit: v.Credit,
			}:
			case <-ExitChan:
				return
			}
		}
	}
}
예제 #24
0
/*
func (this ClientProxy) CreateHTTPClient() {
	if this.start_TLS == false {
		this.client = &http.Client{}
	} else {
		if this.TLS_Path == "" {
			tr := &http.Transport{
				TLSClientConfig:    &tls.Config{InsecureSkipVerify: true},
				DisableCompression: true}
			this.client = &http.Client{Transport: tr}
		} else {
			pool := x509.NewCertPool()
			caCrt, err := ioutil.ReadFile(this.TLS_Path)
			if err != nil {
				_D("invalid cetificate path: %s", this.TLS_Path)
				return
			}
			pool.AppendCertsFromPEM(caCrt)
			tr := &http.Transport{
				TLSClientConfig: &tls.Config{RootCAs: pool},
			}
			this.client = &http.Client{Transport: tr}
		}
	}
}
*/
func (this ClientProxy) ServeDNS(w dns.ResponseWriter, request *dns.Msg) {
	_LOG("get %s query from %s", request.Question[0].Name, w.RemoteAddr())
	request_bytes, err := request.Pack() //I am not sure it is better to pack directly or using a pointer
	if err != nil {
		SRVFAIL(w, request)
		_D("error in packing request from %s for '%s', error message: %s",
			dns.ResponseWriter.RemoteAddr(w), request.Question[0].Name, err)
		return
	}
	ServerInput := this.SERVERS[rand.Intn(len(this.SERVERS))]
	ipaddress := net.ParseIP(ServerInput)
	var ServerInputurl string
	if this.start_TLS { //if it is TLS, use HTTPS
		if ipaddress.To4() != nil {
			ServerInputurl = "https://" + ServerInput
		} else {
			ServerInputurl = "https://[" + ServerInput + "]"
		}

	} else {
		if ipaddress.To4() != nil {
			ServerInputurl = "http://" + ServerInput
		} else {
			ServerInputurl = "http://[" + ServerInput + "]"
		}
	}

	postBytesReader := bytes.NewReader(request_bytes)

	ServerInputurl = ServerInputurl + "/proxy_dns"

	req, err := http.NewRequest("POST", ServerInputurl, postBytesReader) //need add random here in future
	if err != nil {
		SRVFAIL(w, request)
		_D("error in creating HTTP request from %s for '%s', error message: %s",
			dns.ResponseWriter.RemoteAddr(w), request.Question[0].Name, err)
		return
	}
	req.Header.Add("Host", ServerInput)
	req.Header.Add("Accept", "application/octet-stream")
	req.Header.Add("Content-Type", "application/octet-stream")
	if this.TransPro == UDPcode {
		req.Header.Add("Proxy-DNS-Transport", "UDP")
	} else if this.TransPro == TCPcode {
		req.Header.Add("Proxy-DNS-Transport", "TCP")
	}
	if this.start_TLS == false {
		//HTTP version
		tr := &http.Transport{
			DisableKeepAlives: true,
			TLSNextProto:      nil}
		this.client = &http.Client{Transport: tr}
	} else {
		//HTTPS version disabled certificate verification
		if this.TLS_Path == "" {
			tr := &http.Transport{
				TLSClientConfig:    &tls.Config{InsecureSkipVerify: true},
				DisableCompression: true}
			this.client = &http.Client{Transport: tr}
		} else {
			//HTTPS version allow the certificate manually
			pool := x509.NewCertPool()
			caCrt, err := ioutil.ReadFile(this.TLS_Path)
			if err != nil {
				_D("invalid cetificate path: %s", this.TLS_Path)
				return
			}
			pool.AppendCertsFromPEM(caCrt)
			tr := &http.Transport{
				TLSClientConfig: &tls.Config{RootCAs: pool},
			}
			this.client = &http.Client{Transport: tr}
		}
	}
	resp, err := this.client.Do(req)
	if err != nil {
		SRVFAIL(w, request)
		_D("error in HTTP post request for query from %s for '%s', error message: %s",
			dns.ResponseWriter.RemoteAddr(w), request.Question[0].Name, err)
		return
	}
	if resp.StatusCode >= 500 {
		SRVFAIL(w, request)
		_D("HTTP ERROR: %s", http.StatusText(resp.StatusCode))
	}
	var requestBody []byte
	requestBody, err = ioutil.ReadAll(resp.Body)
	//	nRead, err := resp.Body.Read(requestBody)
	if err != nil {
		// these need to be separate checks, otherwise you will get a nil-reference
		// when you print the error message below!
		SRVFAIL(w, request)
		_D("error in reading HTTP response for query from %s for '%s', error message: %s",
			dns.ResponseWriter.RemoteAddr(w), request.Question[0].Name, err)
		return
	}
	//I not sure whether I should return server fail directly
	//I just found there is a bug here. Body.Read can not read all the contents out, I don't know how to solve it.
	if len(requestBody) < (int)(resp.ContentLength) {
		SRVFAIL(w, request)
		_D("failure reading all HTTP content for query from %s for '%s' (%d of %d bytes read)",
			dns.ResponseWriter.RemoteAddr(w), request.Question[0].Name,
			len(requestBody), (int)(resp.ContentLength))
		return
	}
	var DNSreponse dns.Msg
	err = DNSreponse.Unpack(requestBody)
	if err != nil {
		SRVFAIL(w, request)
		_D("error in packing HTTP response for query from %s for '%s', error message: %s",
			dns.ResponseWriter.RemoteAddr(w), request.Question[0].Name, err)
		return
	}
	err = w.WriteMsg(&DNSreponse)
	if err != nil {
		_D("error in sending DNS response back for query from %s for '%s', error message: %s",
			dns.ResponseWriter.RemoteAddr(w), request.Question[0].Name, err)
		return
	}
}
예제 #25
0
func yamlConvertMessage(m *Message, s *bytes.Buffer) {
	s.WriteString(fmt.Sprint("  type: ", m.Type, "\n"))

	if m.QueryTimeSec != nil && m.QueryTimeNsec != nil {
		t := time.Unix(int64(*m.QueryTimeSec), int64(*m.QueryTimeNsec)).UTC()
		s.WriteString(fmt.Sprint("  query_time: !!timestamp ", t.Format(yamlTimeFormat), "\n"))
	}

	if m.ResponseTimeSec != nil && m.ResponseTimeNsec != nil {
		t := time.Unix(int64(*m.ResponseTimeSec), int64(*m.ResponseTimeNsec)).UTC()
		s.WriteString(fmt.Sprint("  response_time: !!timestamp ", t.Format(yamlTimeFormat), "\n"))
	}

	if m.SocketFamily != nil {
		s.WriteString(fmt.Sprint("  socket_family: ", m.SocketFamily, "\n"))
	}

	if m.SocketProtocol != nil {
		s.WriteString(fmt.Sprint("  socket_protocol: ", m.SocketProtocol, "\n"))
	}

	if m.QueryAddress != nil {
		s.WriteString(fmt.Sprint("  query_address: ", net.IP(m.QueryAddress), "\n"))
	}

	if m.ResponseAddress != nil {
		s.WriteString(fmt.Sprint("  response_address: ", net.IP(m.ResponseAddress), "\n"))
	}

	if m.QueryPort != nil {
		s.WriteString(fmt.Sprint("  query_port: ", *m.QueryPort, "\n"))
	}

	if m.ResponsePort != nil {
		s.WriteString(fmt.Sprint("  response_port: ", *m.ResponsePort, "\n"))
	}

	if m.QueryZone != nil {
		name, _, err := dns.UnpackDomainName(m.QueryZone, 0)
		if err != nil {
			s.WriteString("  # query_zone: parse failed\n")
		} else {
			s.WriteString(fmt.Sprint("  query_zone: ", strconv.Quote(name), "\n"))
		}
	}

	if m.QueryMessage != nil {
		msg := new(dns.Msg)
		err := msg.Unpack(m.QueryMessage)
		if err != nil {
			s.WriteString("  # query_message: parse failed\n")
		} else {
			s.WriteString("  query_message: |\n")
			s.WriteString("    " + strings.Replace(strings.TrimSpace(msg.String()), "\n", "\n    ", -1) + "\n")
		}
	}
	if m.ResponseMessage != nil {
		msg := new(dns.Msg)
		err := msg.Unpack(m.ResponseMessage)
		if err != nil {
			s.WriteString(fmt.Sprint("  # response_message: parse failed: ", err, "\n"))
		} else {
			s.WriteString("  response_message: |\n")
			s.WriteString("    " + strings.Replace(strings.TrimSpace(msg.String()), "\n", "\n    ", -1) + "\n")
		}
	}
	s.WriteString("---\n")
}
예제 #26
0
//not sure how to make a server fail, error 501?
func (this Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	TransProString := r.Header.Get("Proxy-DNS-Transport")
	if TransProString == "TCP" {
		this.TransPro = TCPcode
	} else if TransProString == "UDP" {
		this.TransPro = UDPcode
	} else {
		_D("Transport protol not udp or tcp")
		http.Error(w, "Server Error: unknown transport protocol", 415)
		return
	}
	contentTypeStr := r.Header.Get("Content-Type")
	if contentTypeStr != "application/octet-stream" {
		_D("Content-Type illegal")
		http.Error(w, "Server Error: unknown content type", 415)
		return
	}
	var requestBody []byte
	requestBody, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "Server Error: error in reading request", 400)
		_D("error in reading HTTP request, error message: %s", err)
		return
	}
	if len(requestBody) < (int)(r.ContentLength) {
		http.Error(w, "Server Error: error in reading request", 400)
		_D("fail to read all HTTP content")
		return
	}
	var dnsRequest dns.Msg
	err = dnsRequest.Unpack(requestBody)
	if err != nil {
		http.Error(w, "Server Error: bad DNS request", 400)
		_D("error in packing HTTP response to DNS, error message: %s", err)
		return
	}
	/*
		dnsClient := new(dns.Client)
		if dnsClient == nil {
			http.Error(w, "Server Error", 500)
			_D("cannot create DNS client")
			return
		}
		dnsClient.ReadTimeout = this.timeout
		dnsClient.WriteTimeout = this.timeout
		dnsClient.Net = TransProString
		//will use a parameter to let user address resolver in future
		dnsResponse, RTT, err := dnsClient.Exchange(&dnsRequest, this.SERVERS[rand.Intn(len(this.SERVERS))])
		//dnsResponse, RTT, err := dnsClient.Exchange(&dnsRequest, this.SERVERS[0])
		if err != nil {
			_D("error in communicate with resolver, error message: %s", err)
			http.Error(w, "Server Error", 500)
			return
		} else {
			_D("request took %s", RTT)
		}
		if dnsResponse == nil {
			_D("no response back")
			http.Error(w, "Server Error:No Recursive response", 500)
			return
		}*/
	dnsResponse, err := this.DoDNSquery(dnsRequest, TransProString, this.SERVERS, this.timeout)
	if err != nil {
		_D("error in communicate with resolver, error message: %s", err)
		http.Error(w, err.Error(), 500)
		return
	}
	if dnsResponse == nil {
		_D("no response back")
		http.Error(w, "Server Error:No Recursive response", 500)
		return
	}
	response_bytes, err := dnsResponse.Pack()
	if err != nil {
		http.Error(w, "Server Error: error packing reply", 500)
		_D("error in packing request, error message: %s", err)
		return
	}
	_, err = w.Write(response_bytes)
	if err != nil {
		_D("Can not write response rightly, error message: %s", err)
		return
	}
	//don't know how to creat a response here
}
예제 #27
0
func textConvertMessage(m *Message, s *bytes.Buffer) {
	isQuery := false
	printQueryAddress := false

	switch *m.Type {
	case Message_CLIENT_QUERY,
		Message_RESOLVER_QUERY,
		Message_AUTH_QUERY,
		Message_FORWARDER_QUERY,
		Message_TOOL_QUERY:
		isQuery = true
	case Message_CLIENT_RESPONSE,
		Message_RESOLVER_RESPONSE,
		Message_AUTH_RESPONSE,
		Message_FORWARDER_RESPONSE,
		Message_TOOL_RESPONSE:
		isQuery = false
	default:
		s.WriteString("[unhandled Message.Type]\n")
		return
	}

	if isQuery {
		textConvertTime(s, m.QueryTimeSec, m.QueryTimeNsec)
	} else {
		textConvertTime(s, m.ResponseTimeSec, m.ResponseTimeNsec)
	}
	s.WriteString(" ")

	switch *m.Type {
	case Message_CLIENT_QUERY,
		Message_CLIENT_RESPONSE:
		{
			s.WriteString("C")
		}
	case Message_RESOLVER_QUERY,
		Message_RESOLVER_RESPONSE:
		{
			s.WriteString("R")
		}
	case Message_AUTH_QUERY,
		Message_AUTH_RESPONSE:
		{
			s.WriteString("A")
		}
	case Message_FORWARDER_QUERY,
		Message_FORWARDER_RESPONSE:
		{
			s.WriteString("F")
		}
	case Message_STUB_QUERY,
		Message_STUB_RESPONSE:
		{
			s.WriteString("S")
		}
	case Message_TOOL_QUERY,
		Message_TOOL_RESPONSE:
		{
			s.WriteString("T")
		}
	}

	if isQuery {
		s.WriteString("Q ")
	} else {
		s.WriteString("R ")
	}

	switch *m.Type {
	case Message_CLIENT_QUERY,
		Message_CLIENT_RESPONSE,
		Message_AUTH_QUERY,
		Message_AUTH_RESPONSE:
		printQueryAddress = true
	}

	if printQueryAddress {
		textConvertIP(s, m.QueryAddress)
	} else {
		textConvertIP(s, m.ResponseAddress)
	}
	s.WriteString(" ")

	if m.SocketProtocol != nil {
		s.WriteString(m.SocketProtocol.String())
	}
	s.WriteString(" ")

	var err error
	msg := new(dns.Msg)
	if isQuery {
		s.WriteString(strconv.Itoa(len(m.QueryMessage)))
		s.WriteString("b ")
		err = msg.Unpack(m.QueryMessage)
	} else {
		s.WriteString(strconv.Itoa(len(m.ResponseMessage)))
		s.WriteString("b ")
		err = msg.Unpack(m.ResponseMessage)
	}

	if err != nil {
		s.WriteString("X ")
	} else {
		s.WriteString("\"" + msg.Question[0].Name + "\" ")
		s.WriteString(dns.Class(msg.Question[0].Qclass).String() + " ")
		s.WriteString(dns.Type(msg.Question[0].Qtype).String())
	}

	s.WriteString("\n")
}