nameserver_udp.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. package dns
  2. import (
  3. "context"
  4. "strings"
  5. "sync"
  6. "sync/atomic"
  7. "time"
  8. "github.com/xtls/xray-core/common"
  9. "github.com/xtls/xray-core/common/errors"
  10. "github.com/xtls/xray-core/common/net"
  11. "github.com/xtls/xray-core/common/protocol/dns"
  12. udp_proto "github.com/xtls/xray-core/common/protocol/udp"
  13. "github.com/xtls/xray-core/common/task"
  14. dns_feature "github.com/xtls/xray-core/features/dns"
  15. "github.com/xtls/xray-core/features/routing"
  16. "github.com/xtls/xray-core/transport/internet/udp"
  17. "golang.org/x/net/dns/dnsmessage"
  18. )
  19. // ClassicNameServer implemented traditional UDP DNS.
  20. type ClassicNameServer struct {
  21. sync.RWMutex
  22. cacheController *CacheController
  23. address *net.Destination
  24. requests map[uint16]*udpDnsRequest
  25. udpServer *udp.Dispatcher
  26. requestsCleanup *task.Periodic
  27. reqID uint32
  28. clientIP net.IP
  29. }
  30. type udpDnsRequest struct {
  31. dnsRequest
  32. ctx context.Context
  33. }
  34. // NewClassicNameServer creates udp server object for remote resolving.
  35. func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher, disableCache bool, serveStale bool, serveExpiredTTL uint32, clientIP net.IP) *ClassicNameServer {
  36. // default to 53 if unspecific
  37. if address.Port == 0 {
  38. address.Port = net.Port(53)
  39. }
  40. s := &ClassicNameServer{
  41. cacheController: NewCacheController(strings.ToUpper(address.String()), disableCache, serveStale, serveExpiredTTL),
  42. address: &address,
  43. requests: make(map[uint16]*udpDnsRequest),
  44. clientIP: clientIP,
  45. }
  46. s.requestsCleanup = &task.Periodic{
  47. Interval: time.Minute,
  48. Execute: s.RequestsCleanup,
  49. }
  50. s.udpServer = udp.NewDispatcher(dispatcher, s.HandleResponse)
  51. errors.LogInfo(context.Background(), "DNS: created UDP client initialized for ", address.NetAddr())
  52. return s
  53. }
  54. // Name implements Server.
  55. func (s *ClassicNameServer) Name() string {
  56. return s.cacheController.name
  57. }
  58. // IsDisableCache implements Server.
  59. func (s *ClassicNameServer) IsDisableCache() bool {
  60. return s.cacheController.disableCache
  61. }
  62. // RequestsCleanup clears expired items from cache
  63. func (s *ClassicNameServer) RequestsCleanup() error {
  64. now := time.Now()
  65. s.Lock()
  66. defer s.Unlock()
  67. if len(s.requests) == 0 {
  68. return errors.New(s.Name(), " nothing to do. stopping...")
  69. }
  70. for id, req := range s.requests {
  71. if req.expire.Before(now) {
  72. delete(s.requests, id)
  73. }
  74. }
  75. if len(s.requests) == 0 {
  76. s.requests = make(map[uint16]*udpDnsRequest)
  77. }
  78. return nil
  79. }
  80. // HandleResponse handles udp response packet from remote DNS server.
  81. func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_proto.Packet) {
  82. payload := packet.Payload
  83. ipRec, err := parseResponse(payload.Bytes())
  84. payload.Release()
  85. if err != nil {
  86. errors.LogErrorInner(ctx, err, s.Name(), " fail to parse responded DNS udp")
  87. return
  88. }
  89. s.Lock()
  90. id := ipRec.ReqID
  91. req, ok := s.requests[id]
  92. if ok {
  93. // remove the pending request
  94. delete(s.requests, id)
  95. }
  96. s.Unlock()
  97. if !ok {
  98. errors.LogErrorInner(ctx, err, s.Name(), " cannot find the pending request")
  99. return
  100. }
  101. // if truncated, retry with EDNS0 option(udp payload size: 1350)
  102. if ipRec.RawHeader.Truncated {
  103. // if already has EDNS0 option, no need to retry
  104. if len(req.msg.Additionals) == 0 {
  105. // copy necessary meta data from original request
  106. // and add EDNS0 option
  107. opt := new(dnsmessage.Resource)
  108. common.Must(opt.Header.SetEDNS0(1350, 0xfe00, true))
  109. opt.Body = &dnsmessage.OPTResource{}
  110. newMsg := *req.msg
  111. newReq := *req
  112. newMsg.Additionals = append(newMsg.Additionals, *opt)
  113. newMsg.ID = s.newReqID()
  114. newReq.msg = &newMsg
  115. s.addPendingRequest(&newReq)
  116. b, _ := dns.PackMessage(newReq.msg)
  117. copyDest := net.UDPDestination(s.address.Address, s.address.Port)
  118. b.UDP = &copyDest
  119. s.udpServer.Dispatch(toDnsContext(newReq.ctx, s.address.String()), *s.address, b)
  120. return
  121. }
  122. }
  123. s.cacheController.updateRecord(&req.dnsRequest, ipRec)
  124. }
  125. func (s *ClassicNameServer) newReqID() uint16 {
  126. return uint16(atomic.AddUint32(&s.reqID, 1))
  127. }
  128. func (s *ClassicNameServer) addPendingRequest(req *udpDnsRequest) {
  129. s.Lock()
  130. id := req.msg.ID
  131. req.expire = time.Now().Add(time.Second * 8)
  132. s.requests[id] = req
  133. s.Unlock()
  134. common.Must(s.requestsCleanup.Start())
  135. }
  136. // getCacheController implements CachedNameserver.
  137. func (s *ClassicNameServer) getCacheController() *CacheController {
  138. return s.cacheController
  139. }
  140. // sendQuery implements CachedNameserver.
  141. func (s *ClassicNameServer) sendQuery(ctx context.Context, _ chan<- error, fqdn string, option dns_feature.IPOption) {
  142. errors.LogInfo(ctx, s.Name(), " querying DNS for: ", fqdn)
  143. reqs := buildReqMsgs(fqdn, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
  144. for _, req := range reqs {
  145. udpReq := &udpDnsRequest{
  146. dnsRequest: *req,
  147. ctx: ctx,
  148. }
  149. s.addPendingRequest(udpReq)
  150. b, _ := dns.PackMessage(req.msg)
  151. copyDest := net.UDPDestination(s.address.Address, s.address.Port)
  152. b.UDP = &copyDest
  153. s.udpServer.Dispatch(toDnsContext(ctx, s.address.String()), *s.address, b)
  154. }
  155. }
  156. // QueryIP implements Server.
  157. func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
  158. return queryIP(ctx, s, domain, option)
  159. }