github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/edgemesh/pkg/dns/dns.go (about)

     1  package dns
     2  
     3  import (
     4  	"bufio"
     5  	"encoding/binary"
     6  	"errors"
     7  	"fmt"
     8  	"net"
     9  	"os"
    10  	"strings"
    11  	"time"
    12  	"unsafe"
    13  
    14  	"k8s.io/klog"
    15  
    16  	"github.com/kubeedge/kubeedge/edge/pkg/metamanager/client"
    17  	"github.com/kubeedge/kubeedge/edgemesh/pkg/common"
    18  	"github.com/kubeedge/kubeedge/edgemesh/pkg/config"
    19  	"github.com/kubeedge/kubeedge/edgemesh/pkg/listener"
    20  )
    21  
    22  type Event int
    23  
    24  var (
    25  	// default docker0
    26  	ifi = "docker0"
    27  	// QR: 0 represents query, 1 represents response
    28  	dnsQR       = uint16(0x8000)
    29  	oneByteSize = uint16(1)
    30  	twoByteSize = uint16(2)
    31  	ttl         = uint32(64)
    32  )
    33  
    34  const (
    35  	// 1 for ipv4
    36  	aRecord           = 1
    37  	bufSize           = 1024
    38  	errNotImplemented = uint16(0x0004)
    39  	errRefused        = uint16(0x0005)
    40  	eventNothing      = Event(0)
    41  	eventUpstream     = Event(1)
    42  	eventNxDomain     = Event(2)
    43  )
    44  
    45  type dnsHeader struct {
    46  	id      uint16
    47  	flags   uint16
    48  	qdCount uint16
    49  	anCount uint16
    50  	nsCount uint16
    51  	arCount uint16
    52  }
    53  
    54  type dnsQuestion struct {
    55  	from    *net.UDPAddr
    56  	head    *dnsHeader
    57  	name    []byte
    58  	queByte []byte
    59  	qType   uint16
    60  	qClass  uint16
    61  	queNum  uint16
    62  	event   Event
    63  }
    64  
    65  type dnsAnswer struct {
    66  	name    []byte
    67  	qType   uint16
    68  	qClass  uint16
    69  	ttl     uint32
    70  	dataLen uint16
    71  	addr    []byte
    72  }
    73  
    74  // metaClient is a query client
    75  var metaClient client.CoreInterface
    76  
    77  // dnsConn saves DNS protocol
    78  var dnsConn *net.UDPConn
    79  
    80  // Start is for external call
    81  func Start() {
    82  	startDNS()
    83  }
    84  
    85  // startDNS starts edgemesh dns server
    86  func startDNS() {
    87  	// init meta client
    88  	metaClient = client.New()
    89  	// get dns listen ip
    90  	lip, err := common.GetInterfaceIP(ifi)
    91  	if err != nil {
    92  		klog.Errorf("[EdgeMesh] get dns listen ip err: %v", err)
    93  		return
    94  	}
    95  
    96  	laddr := &net.UDPAddr{
    97  		IP:   lip,
    98  		Port: 53,
    99  	}
   100  	udpConn, err := net.ListenUDP("udp", laddr)
   101  	if err != nil {
   102  		klog.Errorf("[EdgeMesh] dns server listen on %v error: %v", laddr, err)
   103  		return
   104  	}
   105  	defer udpConn.Close()
   106  	dnsConn = udpConn
   107  	for {
   108  		req := make([]byte, bufSize)
   109  		n, from, err := dnsConn.ReadFromUDP(req)
   110  		if err != nil || n <= 0 {
   111  			klog.Errorf("[EdgeMesh] dns server read from udp error: %v", err)
   112  			continue
   113  		}
   114  
   115  		que, err := parseDNSQuery(req[:n])
   116  		if err != nil {
   117  			continue
   118  		}
   119  
   120  		que.from = from
   121  
   122  		rsp := make([]byte, 0)
   123  		rsp, err = recordHandle(que, req[:n])
   124  		if err != nil {
   125  			klog.Warningf("[EdgeMesh] failed to resolve dns: %v", err)
   126  			continue
   127  		}
   128  		dnsConn.WriteTo(rsp, from)
   129  	}
   130  }
   131  
   132  // recordHandle returns the answer for the dns question
   133  func recordHandle(que *dnsQuestion, req []byte) (rsp []byte, err error) {
   134  	var exist bool
   135  	var ip string
   136  	// qType should be 1 for ipv4
   137  	if que.name != nil && que.qType == aRecord {
   138  		domainName := string(que.name)
   139  		exist, ip = lookupFromMetaManager(domainName)
   140  	}
   141  
   142  	if !exist || que.event == eventUpstream {
   143  		// if this service doesn't belongs to this cluster
   144  		go getFromRealDNS(req, que.from)
   145  		return rsp, fmt.Errorf("get from real dns")
   146  	}
   147  
   148  	address := net.ParseIP(ip).To4()
   149  	if address == nil {
   150  		que.event = eventNxDomain
   151  	}
   152  	// gen
   153  	pre := modifyRspPrefix(que)
   154  	rsp = append(rsp, pre...)
   155  	if que.event != eventNothing {
   156  		return rsp, nil
   157  	}
   158  	// create a deceptive resp, if no error
   159  	dnsAns := &dnsAnswer{
   160  		name:    que.name,
   161  		qType:   que.qType,
   162  		qClass:  que.qClass,
   163  		ttl:     ttl,
   164  		dataLen: uint16(len(address)),
   165  		addr:    address,
   166  	}
   167  	ans := dnsAns.getAnswer()
   168  	rsp = append(rsp, ans...)
   169  
   170  	return rsp, nil
   171  }
   172  
   173  // parseDNSQuery converts bytes to *dnsQuestion
   174  func parseDNSQuery(req []byte) (que *dnsQuestion, err error) {
   175  	head := &dnsHeader{}
   176  	head.getHeader(req)
   177  	if !head.isAQuery() {
   178  		return nil, errors.New("not a dns query, ignore")
   179  	}
   180  	que = &dnsQuestion{
   181  		event: eventNothing,
   182  	}
   183  	// Generally, when the recursive DNS server requests upward, it may
   184  	// initiate a resolution request for multiple aliases/domain names
   185  	// at once, Edge DNS does not need to process a message that carries
   186  	// multiple questions at a time.
   187  	if head.qdCount != 1 {
   188  		que.event = eventUpstream
   189  		return
   190  	}
   191  
   192  	offset := uint16(unsafe.Sizeof(dnsHeader{}))
   193  	// DNS NS <ROOT> operation
   194  	if req[offset] == 0x0 {
   195  		que.event = eventUpstream
   196  		return
   197  	}
   198  	que.getQuestion(req, offset, head)
   199  	err = nil
   200  	return
   201  }
   202  
   203  // isAQuery judges if the dns pkg is a query
   204  func (h *dnsHeader) isAQuery() bool {
   205  	if h.flags&dnsQR != dnsQR {
   206  		return true
   207  	}
   208  	return false
   209  }
   210  
   211  // getHeader gets dns pkg head
   212  func (h *dnsHeader) getHeader(req []byte) {
   213  	h.id = binary.BigEndian.Uint16(req[0:2])
   214  	h.flags = binary.BigEndian.Uint16(req[2:4])
   215  	h.qdCount = binary.BigEndian.Uint16(req[4:6])
   216  	h.anCount = binary.BigEndian.Uint16(req[6:8])
   217  	h.nsCount = binary.BigEndian.Uint16(req[8:10])
   218  	h.arCount = binary.BigEndian.Uint16(req[10:12])
   219  }
   220  
   221  // getQuestion gets a dns question
   222  func (q *dnsQuestion) getQuestion(req []byte, offset uint16, head *dnsHeader) {
   223  	ost := offset
   224  	tmp := ost
   225  	ost = q.getQName(req, ost)
   226  	q.qType = binary.BigEndian.Uint16(req[ost : ost+twoByteSize])
   227  	ost += twoByteSize
   228  	q.qClass = binary.BigEndian.Uint16(req[ost : ost+twoByteSize])
   229  	ost += twoByteSize
   230  	q.head = head
   231  	q.queByte = req[tmp:ost]
   232  }
   233  
   234  // getAnswer generates answer for the dns question
   235  func (da *dnsAnswer) getAnswer() (answer []byte) {
   236  	answer = make([]byte, 0)
   237  
   238  	if da.qType == aRecord {
   239  		answer = append(answer, 0xc0)
   240  		answer = append(answer, 0x0c)
   241  
   242  		tmp16 := make([]byte, 2)
   243  		tmp32 := make([]byte, 4)
   244  
   245  		binary.BigEndian.PutUint16(tmp16, da.qType)
   246  		answer = append(answer, tmp16...)
   247  		binary.BigEndian.PutUint16(tmp16, da.qClass)
   248  		answer = append(answer, tmp16...)
   249  		binary.BigEndian.PutUint32(tmp32, da.ttl)
   250  		answer = append(answer, tmp32...)
   251  		binary.BigEndian.PutUint16(tmp16, da.dataLen)
   252  		answer = append(answer, tmp16...)
   253  		answer = append(answer, da.addr...)
   254  	}
   255  
   256  	return answer
   257  }
   258  
   259  // getQName gets dns question qName
   260  func (q *dnsQuestion) getQName(req []byte, offset uint16) uint16 {
   261  	ost := offset
   262  
   263  	for {
   264  		// one byte to suggest length
   265  		qbyte := uint16(req[ost])
   266  
   267  		// qName ends with 0x00, and 0x00 should not be included
   268  		if qbyte == 0x00 {
   269  			q.name = q.name[:uint16(len(q.name))-oneByteSize]
   270  			return ost + oneByteSize
   271  		}
   272  		// step forward one more byte and get the real stuff
   273  		ost += oneByteSize
   274  		q.name = append(q.name, req[ost:ost+qbyte]...)
   275  		// add "." symbol
   276  		q.name = append(q.name, 0x2e)
   277  		ost += qbyte
   278  	}
   279  }
   280  
   281  // lookupFromMetaManager confirms if the service exists
   282  func lookupFromMetaManager(serviceUrl string) (exist bool, ip string) {
   283  	name, namespace := common.SplitServiceKey(serviceUrl)
   284  	s, _ := metaClient.Services(namespace).Get(name)
   285  	if s != nil {
   286  		svcName := namespace + "." + name
   287  		ip := listener.GetServiceServer(svcName)
   288  		klog.Infof("[EdgeMesh] dns server parse %s ip %s", serviceUrl, ip)
   289  		return true, ip
   290  	}
   291  	klog.Errorf("[EdgeMesh] service %s is not found in this cluster", serviceUrl)
   292  	return false, ""
   293  }
   294  
   295  // getFromRealDNS returns a dns response from real dns servers
   296  func getFromRealDNS(req []byte, from *net.UDPAddr) {
   297  	rsp := make([]byte, 0)
   298  	ips, err := parseNameServer()
   299  	if err != nil {
   300  		klog.Errorf("[EdgeMesh] parse nameserver err: %v", err)
   301  		return
   302  	}
   303  
   304  	laddr := &net.UDPAddr{
   305  		IP:   net.IPv4zero,
   306  		Port: 0,
   307  	}
   308  
   309  	// get from real dns servers
   310  	for _, ip := range ips {
   311  		raddr := &net.UDPAddr{
   312  			IP:   ip,
   313  			Port: 53,
   314  		}
   315  		conn, err := net.DialUDP("udp", laddr, raddr)
   316  		if err != nil {
   317  			continue
   318  		}
   319  		defer conn.Close()
   320  		_, err = conn.Write(req)
   321  		if err != nil {
   322  			continue
   323  		}
   324  		if err = conn.SetReadDeadline(time.Now().Add(time.Minute)); err != nil {
   325  			continue
   326  		}
   327  		var n int
   328  		buf := make([]byte, bufSize)
   329  		n, err = conn.Read(buf)
   330  		if err != nil {
   331  			continue
   332  		}
   333  
   334  		if n > 0 {
   335  			rsp = append(rsp, buf[:n]...)
   336  			dnsConn.WriteToUDP(rsp, from)
   337  			break
   338  		}
   339  	}
   340  }
   341  
   342  // parseNameServer gets all real nameservers from the resolv.conf
   343  func parseNameServer() ([]net.IP, error) {
   344  	file, err := os.Open("/etc/resolv.conf")
   345  	if err != nil {
   346  		return nil, fmt.Errorf("error opening /etc/resolv.conf: %v", err)
   347  	}
   348  	defer file.Close()
   349  
   350  	scan := bufio.NewScanner(file)
   351  	scan.Split(bufio.ScanLines)
   352  
   353  	ip := make([]net.IP, 0)
   354  
   355  	for scan.Scan() {
   356  		serverString := scan.Text()
   357  		if strings.Contains(serverString, "nameserver") {
   358  			tmpString := strings.Replace(serverString, "nameserver", "", 1)
   359  			nameserver := strings.TrimSpace(tmpString)
   360  			sip := net.ParseIP(nameserver)
   361  			if sip != nil && !sip.Equal(config.Config.ListenIP) {
   362  				ip = append(ip, sip)
   363  			}
   364  		}
   365  	}
   366  	if len(ip) == 0 {
   367  		return nil, fmt.Errorf("there is no nameserver in /etc/resolv.conf")
   368  	}
   369  	return ip, nil
   370  }
   371  
   372  // modifyRspPrefix generates a dns response head
   373  func modifyRspPrefix(que *dnsQuestion) (pre []byte) {
   374  	if que == nil {
   375  		return
   376  	}
   377  	// use head in que
   378  	rspHead := que.head
   379  	rspHead.convertQueryRsp(true)
   380  	if que.qType == aRecord {
   381  		rspHead.setAnswerNum(1)
   382  	} else {
   383  		rspHead.setAnswerNum(0)
   384  	}
   385  
   386  	rspHead.setRspRCode(que)
   387  	pre = rspHead.getByteFromDNSHeader()
   388  
   389  	pre = append(pre, que.queByte...)
   390  	return
   391  }
   392  
   393  // convertQueryRsp converts a dns question head to a response head
   394  func (h *dnsHeader) convertQueryRsp(isRsp bool) {
   395  	if isRsp {
   396  		h.flags |= dnsQR
   397  	} else {
   398  		h.flags |= dnsQR
   399  	}
   400  }
   401  
   402  // setAnswerNum sets the answer num for dns head
   403  func (h *dnsHeader) setAnswerNum(num uint16) {
   404  	h.anCount = num
   405  }
   406  
   407  // setRspRCode sets dns response return code
   408  func (h *dnsHeader) setRspRCode(que *dnsQuestion) {
   409  	if que.qType != aRecord {
   410  		h.flags &= (^errNotImplemented)
   411  		h.flags |= errNotImplemented
   412  	} else if que.event == eventNxDomain {
   413  		h.flags &= (^errRefused)
   414  		h.flags |= errRefused
   415  	}
   416  }
   417  
   418  // getByteFromDNSHeader converts dnsHeader to bytes
   419  func (h *dnsHeader) getByteFromDNSHeader() (rspHead []byte) {
   420  	rspHead = make([]byte, unsafe.Sizeof(*h))
   421  
   422  	idxTransactionID := unsafe.Sizeof(h.id)
   423  	idxFlags := unsafe.Sizeof(h.flags) + idxTransactionID
   424  	idxQDCount := unsafe.Sizeof(h.anCount) + idxFlags
   425  	idxANCount := unsafe.Sizeof(h.anCount) + idxQDCount
   426  	idxNSCount := unsafe.Sizeof(h.nsCount) + idxANCount
   427  	idxARCount := unsafe.Sizeof(h.arCount) + idxNSCount
   428  
   429  	binary.BigEndian.PutUint16(rspHead[:idxTransactionID], h.id)
   430  	binary.BigEndian.PutUint16(rspHead[idxTransactionID:idxFlags], h.flags)
   431  	binary.BigEndian.PutUint16(rspHead[idxFlags:idxQDCount], h.qdCount)
   432  	binary.BigEndian.PutUint16(rspHead[idxQDCount:idxANCount], h.anCount)
   433  	binary.BigEndian.PutUint16(rspHead[idxANCount:idxNSCount], h.nsCount)
   434  	binary.BigEndian.PutUint16(rspHead[idxNSCount:idxARCount], h.arCount)
   435  	return
   436  }