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 }