mirror of
				https://github.com/nadoo/glider.git
				synced 2025-11-04 07:42:38 +08:00 
			
		
		
		
	dns: add some comment
This commit is contained in:
		
							parent
							
								
									969034fb97
								
							
						
					
					
						commit
						2e10672c3b
					
				
							
								
								
									
										256
									
								
								dns.go
									
									
									
									
									
								
							
							
						
						
									
										256
									
								
								dns.go
									
									
									
									
									
								
							@ -10,11 +10,8 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DNSUDPHeaderLen is the length of UDP dns msg header
 | 
					// DNSHeaderLen is the length of dns msg header
 | 
				
			||||||
const DNSUDPHeaderLen = 12
 | 
					const DNSHeaderLen = 12
 | 
				
			||||||
 | 
					 | 
				
			||||||
// DNSTCPHeaderLen is the length of TCP dns msg header
 | 
					 | 
				
			||||||
const DNSTCPHeaderLen = 2 + DNSUDPHeaderLen
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DNSUDPMaxLen is the max size of udp dns request.
 | 
					// DNSUDPMaxLen is the max size of udp dns request.
 | 
				
			||||||
// https://tools.ietf.org/html/rfc1035#section-4.2.1
 | 
					// https://tools.ietf.org/html/rfc1035#section-4.2.1
 | 
				
			||||||
@ -25,26 +22,114 @@ const DNSTCPHeaderLen = 2 + DNSUDPHeaderLen
 | 
				
			|||||||
// so we should also serve tcp requests.
 | 
					// so we should also serve tcp requests.
 | 
				
			||||||
const DNSUDPMaxLen = 512
 | 
					const DNSUDPMaxLen = 512
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DNSQueryTypeA ipv4
 | 
					// DNSQTypeA ipv4
 | 
				
			||||||
const DNSQueryTypeA = 1
 | 
					const DNSQTypeA = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DNSQueryTypeAAAA ipv6
 | 
					// DNSQTypeAAAA ipv6
 | 
				
			||||||
const DNSQueryTypeAAAA = 28
 | 
					const DNSQTypeAAAA = 28
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type dnsQuery struct {
 | 
					// DNSMsg format
 | 
				
			||||||
	DomainName string
 | 
					// https://tools.ietf.org/html/rfc1035#section-4.1
 | 
				
			||||||
	QueryType  uint16
 | 
					// All communications inside of the domain protocol are carried in a single
 | 
				
			||||||
	QueryClass uint16
 | 
					// format called a message.  The top level format of message is divided
 | 
				
			||||||
	Offset     int
 | 
					// into 5 sections (some of which are empty in certain cases) shown below:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     +---------------------+
 | 
				
			||||||
 | 
					//     |        Header       |
 | 
				
			||||||
 | 
					//     +---------------------+
 | 
				
			||||||
 | 
					//     |       Question      | the question for the name server
 | 
				
			||||||
 | 
					//     +---------------------+
 | 
				
			||||||
 | 
					//     |        Answer       | RRs answering the question
 | 
				
			||||||
 | 
					//     +---------------------+
 | 
				
			||||||
 | 
					//     |      Authority      | RRs pointing toward an authority
 | 
				
			||||||
 | 
					//     +---------------------+
 | 
				
			||||||
 | 
					//     |      Additional     | RRs holding additional information
 | 
				
			||||||
 | 
					type DNSMsg struct {
 | 
				
			||||||
 | 
						DNSHeader
 | 
				
			||||||
 | 
						Questions []*DNSQuestion
 | 
				
			||||||
 | 
						Answers   []*DNSRR
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type dnsAnswer struct {
 | 
					// DNSHeader format
 | 
				
			||||||
	// DomainName string
 | 
					// https://tools.ietf.org/html/rfc1035#section-4.1.1
 | 
				
			||||||
	QueryType  uint16
 | 
					// The header contains the following fields:
 | 
				
			||||||
	QueryClass uint16
 | 
					//
 | 
				
			||||||
	TTL        uint32
 | 
					//                                     1  1  1  1  1  1
 | 
				
			||||||
	DataLength uint16
 | 
					//       0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
 | 
				
			||||||
	Data       []byte
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					//     |                      ID                       |
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					//     |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					//     |                    QDCOUNT                    |
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					//     |                    ANCOUNT                    |
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					//     |                    NSCOUNT                    |
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					//     |                    ARCOUNT                    |
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					type DNSHeader struct {
 | 
				
			||||||
 | 
						ID uint16
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DNSQuestion format
 | 
				
			||||||
 | 
					// https://tools.ietf.org/html/rfc1035#section-4.1.2
 | 
				
			||||||
 | 
					// The question section is used to carry the "question" in most queries,
 | 
				
			||||||
 | 
					// i.e., the parameters that define what is being asked.  The section
 | 
				
			||||||
 | 
					// contains QDCOUNT (usually 1) entries, each of the following format:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//                                     1  1  1  1  1  1
 | 
				
			||||||
 | 
					//       0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					//     |                                               |
 | 
				
			||||||
 | 
					//     /                     QNAME                     /
 | 
				
			||||||
 | 
					//     /                                               /
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					//     |                     QTYPE                     |
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					//     |                     QCLASS                    |
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					type DNSQuestion struct {
 | 
				
			||||||
 | 
						QNAME  string
 | 
				
			||||||
 | 
						QTYPE  uint16
 | 
				
			||||||
 | 
						QCLASS uint16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Offset int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DNSRR format
 | 
				
			||||||
 | 
					// https://tools.ietf.org/html/rfc1035#section-3.2.1
 | 
				
			||||||
 | 
					// All RRs have the same top level format shown below:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//                                     1  1  1  1  1  1
 | 
				
			||||||
 | 
					//       0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					//     |                                               |
 | 
				
			||||||
 | 
					//     /                                               /
 | 
				
			||||||
 | 
					//     /                      NAME                     /
 | 
				
			||||||
 | 
					//     |                                               |
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					//     |                      TYPE                     |
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					//     |                     CLASS                     |
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					//     |                      TTL                      |
 | 
				
			||||||
 | 
					//     |                                               |
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					//     |                   RDLENGTH                    |
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
 | 
				
			||||||
 | 
					//     /                     RDATA                     /
 | 
				
			||||||
 | 
					//     /                                               /
 | 
				
			||||||
 | 
					//     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 | 
				
			||||||
 | 
					type DNSRR struct {
 | 
				
			||||||
 | 
						// NAME string
 | 
				
			||||||
 | 
						TYPE     uint16
 | 
				
			||||||
 | 
						CLASS    uint16
 | 
				
			||||||
 | 
						TTL      uint32
 | 
				
			||||||
 | 
						RDLENGTH uint16
 | 
				
			||||||
 | 
						RDATA    []byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	IP string
 | 
						IP string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -57,12 +142,12 @@ type DNS struct {
 | 
				
			|||||||
	*Forwarder        // as proxy client
 | 
						*Forwarder        // as proxy client
 | 
				
			||||||
	sDialer    Dialer // dialer for server
 | 
						sDialer    Dialer // dialer for server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tunnel bool
 | 
						Tunnel bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dnsServer string
 | 
						DNSServer string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dnsServerMap   map[string]string
 | 
						DNSServerMap   map[string]string
 | 
				
			||||||
	answerHandlers []DNSAnswerHandler
 | 
						AnswerHandlers []DNSAnswerHandler
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewDNS returns a dns forwarder. client[dns.udp] -> glider[tcp] -> forwarder[dns.tcp] -> remote dns addr
 | 
					// NewDNS returns a dns forwarder. client[dns.udp] -> glider[tcp] -> forwarder[dns.tcp] -> remote dns addr
 | 
				
			||||||
@ -71,10 +156,10 @@ func NewDNS(addr, raddr string, sDialer Dialer, tunnel bool) (*DNS, error) {
 | 
				
			|||||||
		Forwarder: NewForwarder(addr, nil),
 | 
							Forwarder: NewForwarder(addr, nil),
 | 
				
			||||||
		sDialer:   sDialer,
 | 
							sDialer:   sDialer,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		tunnel: tunnel,
 | 
							Tunnel: tunnel,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dnsServer:    raddr,
 | 
							DNSServer:    raddr,
 | 
				
			||||||
		dnsServerMap: make(map[string]string),
 | 
							DNSServerMap: make(map[string]string),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return s, nil
 | 
						return s, nil
 | 
				
			||||||
@ -90,31 +175,34 @@ func (s *DNS) ListenAndServe() {
 | 
				
			|||||||
func (s *DNS) ListenAndServeUDP() {
 | 
					func (s *DNS) ListenAndServeUDP() {
 | 
				
			||||||
	c, err := net.ListenPacket("udp", s.addr)
 | 
						c, err := net.ListenPacket("udp", s.addr)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		logf("proxy-dns failed to listen on %s: %v", s.addr, err)
 | 
							logf("proxy-dns failed to listen on %s, error: %v", s.addr, err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer c.Close()
 | 
						defer c.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	logf("proxy-dns listening on udp:%s", s.addr)
 | 
						logf("proxy-dns listening UDP on %s", s.addr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		data := make([]byte, DNSUDPMaxLen)
 | 
							b := make([]byte, DNSUDPMaxLen)
 | 
				
			||||||
 | 
							n, clientAddr, err := c.ReadFrom(b)
 | 
				
			||||||
		n, clientAddr, err := c.ReadFrom(data)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			logf("proxy-dns DNS local read error: %v", err)
 | 
								logf("proxy-dns local read error: %v", err)
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		data = data[:n]
 | 
							reqLen := uint16(n)
 | 
				
			||||||
 | 
							if reqLen <= DNSHeaderLen {
 | 
				
			||||||
 | 
								logf("proxy-dns not enough data")
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							b = b[:n]
 | 
				
			||||||
		go func() {
 | 
							go func() {
 | 
				
			||||||
 | 
								_, respMsg := s.handleReqMsg(reqLen, b)
 | 
				
			||||||
			_, respMsg := s.handleReqMsg(uint16(len(data)), data)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			_, err = c.WriteTo(respMsg, clientAddr)
 | 
								_, err = c.WriteTo(respMsg, clientAddr)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				logf("proxy-dns error in local write: %s\n", err)
 | 
									logf("proxy-dns error in local write: %s", err)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// logf("proxy-dns %s <-> %s, type: %d, %s: %s", clientAddr.String(), dnsServer, query.QueryType, domain, ip)
 | 
								// logf("proxy-dns %s <-> %s, type: %d, %s: %s", clientAddr.String(), dnsServer, query.QueryType, domain, ip)
 | 
				
			||||||
@ -131,7 +219,7 @@ func (s *DNS) ListenAndServeTCP() {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	logf("proxy-dns-tcp listening on tcp:%s", s.addr)
 | 
						logf("proxy-dns-tcp listening TCP on %s", s.addr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		c, err := l.Accept()
 | 
							c, err := l.Accept()
 | 
				
			||||||
@ -157,6 +245,11 @@ func (s *DNS) ServeTCP(c net.Conn) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if reqLen <= DNSHeaderLen {
 | 
				
			||||||
 | 
							logf("proxy-dns not enough data")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reqMsg := make([]byte, reqLen)
 | 
						reqMsg := make([]byte, reqLen)
 | 
				
			||||||
	_, err := io.ReadFull(c, reqMsg)
 | 
						_, err := io.ReadFull(c, reqMsg)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -165,7 +258,6 @@ func (s *DNS) ServeTCP(c net.Conn) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	respLen, respMsg := s.handleReqMsg(reqLen, reqMsg)
 | 
						respLen, respMsg := s.handleReqMsg(reqLen, reqMsg)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err := binary.Write(c, binary.BigEndian, respLen); err != nil {
 | 
						if err := binary.Write(c, binary.BigEndian, respLen); err != nil {
 | 
				
			||||||
		logf("proxy-dns-tcp error in local write respLen: %s\n", err)
 | 
							logf("proxy-dns-tcp error in local write respLen: %s\n", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -178,19 +270,19 @@ func (s *DNS) ServeTCP(c net.Conn) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// handle request msg and return response msg
 | 
					// handle request msg and return response msg
 | 
				
			||||||
func (s *DNS) handleReqMsg(reqLen uint16, reqMsg []byte) (respLen uint16, respMsg []byte) {
 | 
					func (s *DNS) handleReqMsg(reqLen uint16, reqMsg []byte) (respLen uint16, respMsg []byte) {
 | 
				
			||||||
 | 
						// fmt.Printf("dns req len %d:\n%s\n\n", reqLen, hex.Dump(reqMsg[:]))
 | 
				
			||||||
	query, err := parseQuery(reqMsg)
 | 
						query, err := parseQuestion(reqMsg)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		logf("proxy-dns-tcp error in parseQuery reqMsg %s", err)
 | 
							logf("proxy-dns error in parseQuestion reqMsg %s", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dnsServer := s.GetServer(query.DomainName)
 | 
						dnsServer := s.GetServer(query.QNAME)
 | 
				
			||||||
	if s.tunnel {
 | 
						if s.Tunnel {
 | 
				
			||||||
		dnsServer = s.dnsServer
 | 
							dnsServer = s.DNSServer
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc, err := s.sDialer.NextDialer(query.DomainName+":53").Dial("tcp", dnsServer)
 | 
						rc, err := s.sDialer.NextDialer(query.QNAME+":53").Dial("tcp", dnsServer)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		logf("proxy-dns failed to connect to server %v: %v", dnsServer, err)
 | 
							logf("proxy-dns failed to connect to server %v: %v", dnsServer, err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@ -198,21 +290,23 @@ func (s *DNS) handleReqMsg(reqLen uint16, reqMsg []byte) (respLen uint16, respMs
 | 
				
			|||||||
	defer rc.Close()
 | 
						defer rc.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := binary.Write(rc, binary.BigEndian, reqLen); err != nil {
 | 
						if err := binary.Write(rc, binary.BigEndian, reqLen); err != nil {
 | 
				
			||||||
		logf("proxy-dns failed to connect to server %v: %v", dnsServer, err)
 | 
							logf("proxy-dns failed to write req length: %v", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := binary.Write(rc, binary.BigEndian, reqMsg); err != nil {
 | 
						if err := binary.Write(rc, binary.BigEndian, reqMsg); err != nil {
 | 
				
			||||||
		logf("proxy-dns failed to connect to server %v: %v", dnsServer, err)
 | 
							logf("proxy-dns failed to write req message: %v", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := binary.Read(rc, binary.BigEndian, &respLen); err != nil {
 | 
						if err := binary.Read(rc, binary.BigEndian, &respLen); err != nil {
 | 
				
			||||||
		logf("proxy-dns-tcp failed to read response length: %v", err)
 | 
							logf("proxy-dns failed to read response length: %v", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	respMsg = make([]byte, respLen)
 | 
						respMsg = make([]byte, respLen)
 | 
				
			||||||
	_, err = io.ReadFull(rc, respMsg)
 | 
						_, err = io.ReadFull(rc, respMsg)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		logf("proxy-dns-tcp error in read respMsg %s\n", err)
 | 
							logf("proxy-dns error in read respMsg %s\n", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -220,24 +314,23 @@ func (s *DNS) handleReqMsg(reqLen uint16, reqMsg []byte) (respLen uint16, respMs
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	var ip string
 | 
						var ip string
 | 
				
			||||||
	if respLen > 0 {
 | 
						if respLen > 0 {
 | 
				
			||||||
		query, err := parseQuery(respMsg)
 | 
							query, err := parseQuestion(respMsg)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			logf("proxy-dns error in parseQuery respMsg %s", err)
 | 
								logf("proxy-dns error in parseQuestion respMsg %s", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (query.QueryType == DNSQueryTypeA || query.QueryType == DNSQueryTypeAAAA) &&
 | 
							if (query.QTYPE == DNSQTypeA || query.QTYPE == DNSQTypeAAAA) &&
 | 
				
			||||||
			len(respMsg) > query.Offset {
 | 
								len(respMsg) > query.Offset {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			answers := parseAnswers(respMsg[query.Offset:])
 | 
								answers := parseAnswers(respMsg[query.Offset:])
 | 
				
			||||||
 | 
					 | 
				
			||||||
			for _, answer := range answers {
 | 
								for _, answer := range answers {
 | 
				
			||||||
				if answer.IP != "" {
 | 
									if answer.IP != "" {
 | 
				
			||||||
					ip += answer.IP + ","
 | 
										ip += answer.IP + ","
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				for _, h := range s.answerHandlers {
 | 
									for _, h := range s.AnswerHandlers {
 | 
				
			||||||
					h(query.DomainName, answer.IP)
 | 
										h(query.QNAME, answer.IP)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -249,36 +342,35 @@ func (s *DNS) handleReqMsg(reqLen uint16, reqMsg []byte) (respLen uint16, respMs
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// SetServer .
 | 
					// SetServer .
 | 
				
			||||||
func (s *DNS) SetServer(domain, server string) {
 | 
					func (s *DNS) SetServer(domain, server string) {
 | 
				
			||||||
	s.dnsServerMap[domain] = server
 | 
						s.DNSServerMap[domain] = server
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetServer .
 | 
					// GetServer .
 | 
				
			||||||
func (s *DNS) GetServer(domain string) string {
 | 
					func (s *DNS) GetServer(domain string) string {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	domainParts := strings.Split(domain, ".")
 | 
						domainParts := strings.Split(domain, ".")
 | 
				
			||||||
	length := len(domainParts)
 | 
						length := len(domainParts)
 | 
				
			||||||
	for i := length - 2; i >= 0; i-- {
 | 
						for i := length - 2; i >= 0; i-- {
 | 
				
			||||||
		domain := strings.Join(domainParts[i:length], ".")
 | 
							domain := strings.Join(domainParts[i:length], ".")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if server, ok := s.dnsServerMap[domain]; ok {
 | 
							if server, ok := s.DNSServerMap[domain]; ok {
 | 
				
			||||||
			return server
 | 
								return server
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return s.dnsServer
 | 
						return s.DNSServer
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AddAnswerHandler .
 | 
					// AddAnswerHandler .
 | 
				
			||||||
func (s *DNS) AddAnswerHandler(h DNSAnswerHandler) {
 | 
					func (s *DNS) AddAnswerHandler(h DNSAnswerHandler) {
 | 
				
			||||||
	s.answerHandlers = append(s.answerHandlers, h)
 | 
						s.AnswerHandlers = append(s.AnswerHandlers, h)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func parseQuery(p []byte) (*dnsQuery, error) {
 | 
					func parseQuestion(p []byte) (*DNSQuestion, error) {
 | 
				
			||||||
	q := &dnsQuery{}
 | 
						q := &DNSQuestion{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var i int
 | 
						var i int
 | 
				
			||||||
	var domain []byte
 | 
						var domain []byte
 | 
				
			||||||
	for i = DNSUDPHeaderLen; i < len(p); {
 | 
						for i = DNSHeaderLen; i < len(p); {
 | 
				
			||||||
		l := int(p[i])
 | 
							l := int(p[i])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if l == 0 {
 | 
							if l == 0 {
 | 
				
			||||||
@ -292,21 +384,21 @@ func parseQuery(p []byte) (*dnsQuery, error) {
 | 
				
			|||||||
		i = i + l + 1
 | 
							i = i + l + 1
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	q.DomainName = string(domain[:len(domain)-1])
 | 
						q.QNAME = string(domain[:len(domain)-1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(p) < i+4 {
 | 
						if len(p) < i+4 {
 | 
				
			||||||
		return nil, errors.New("parseQuery error, not enough data")
 | 
							return nil, errors.New("parseQuestion error, not enough data")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	q.QueryType = binary.BigEndian.Uint16(p[i:])
 | 
						q.QTYPE = binary.BigEndian.Uint16(p[i:])
 | 
				
			||||||
	q.QueryClass = binary.BigEndian.Uint16(p[i+2:])
 | 
						q.QCLASS = binary.BigEndian.Uint16(p[i+2:])
 | 
				
			||||||
	q.Offset = i + 4
 | 
						q.Offset = i + 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return q, nil
 | 
						return q, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func parseAnswers(p []byte) []*dnsAnswer {
 | 
					func parseAnswers(p []byte) []*DNSRR {
 | 
				
			||||||
	var answers []*dnsAnswer
 | 
						var answers []*DNSRR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := 0; i < len(p); {
 | 
						for i := 0; i < len(p); {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -323,23 +415,23 @@ func parseAnswers(p []byte) []*dnsAnswer {
 | 
				
			|||||||
			break
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		answer := &dnsAnswer{}
 | 
							answer := &DNSRR{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		answer.QueryType = binary.BigEndian.Uint16(p[i:])
 | 
							answer.TYPE = binary.BigEndian.Uint16(p[i:])
 | 
				
			||||||
		answer.QueryClass = binary.BigEndian.Uint16(p[i+2:])
 | 
							answer.CLASS = binary.BigEndian.Uint16(p[i+2:])
 | 
				
			||||||
		answer.TTL = binary.BigEndian.Uint32(p[i+4:])
 | 
							answer.TTL = binary.BigEndian.Uint32(p[i+4:])
 | 
				
			||||||
		answer.DataLength = binary.BigEndian.Uint16(p[i+8:])
 | 
							answer.RDLENGTH = binary.BigEndian.Uint16(p[i+8:])
 | 
				
			||||||
		answer.Data = p[i+10 : i+10+int(answer.DataLength)]
 | 
							answer.RDATA = p[i+10 : i+10+int(answer.RDLENGTH)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if answer.QueryType == DNSQueryTypeA {
 | 
							if answer.TYPE == DNSQTypeA {
 | 
				
			||||||
			answer.IP = net.IP(answer.Data[:net.IPv4len]).String()
 | 
								answer.IP = net.IP(answer.RDATA[:net.IPv4len]).String()
 | 
				
			||||||
		} else if answer.QueryType == DNSQueryTypeAAAA {
 | 
							} else if answer.TYPE == DNSQTypeAAAA {
 | 
				
			||||||
			answer.IP = net.IP(answer.Data[:net.IPv6len]).String()
 | 
								answer.IP = net.IP(answer.RDATA[:net.IPv6len]).String()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		answers = append(answers, answer)
 | 
							answers = append(answers, answer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		i = i + 10 + int(answer.DataLength)
 | 
							i = i + 10 + int(answer.RDLENGTH)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return answers
 | 
						return answers
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user