dnscommon.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // +build !confonly
  2. package dns
  3. import (
  4. "encoding/binary"
  5. "strings"
  6. "time"
  7. "golang.org/x/net/dns/dnsmessage"
  8. "github.com/v2fly/v2ray-core/v4/common"
  9. "github.com/v2fly/v2ray-core/v4/common/errors"
  10. "github.com/v2fly/v2ray-core/v4/common/net"
  11. dns_feature "github.com/v2fly/v2ray-core/v4/features/dns"
  12. )
  13. // Fqdn normalize domain make sure it ends with '.'
  14. func Fqdn(domain string) string {
  15. if len(domain) > 0 && strings.HasSuffix(domain, ".") {
  16. return domain
  17. }
  18. return domain + "."
  19. }
  20. type record struct {
  21. A *IPRecord
  22. AAAA *IPRecord
  23. }
  24. // IPRecord is a cacheable item for a resolved domain
  25. type IPRecord struct {
  26. ReqID uint16
  27. IP []net.Address
  28. Expire time.Time
  29. RCode dnsmessage.RCode
  30. }
  31. func (r *IPRecord) getIPs() ([]net.Address, error) {
  32. if r == nil || r.Expire.Before(time.Now()) {
  33. return nil, errRecordNotFound
  34. }
  35. if r.RCode != dnsmessage.RCodeSuccess {
  36. return nil, dns_feature.RCodeError(r.RCode)
  37. }
  38. return r.IP, nil
  39. }
  40. func isNewer(baseRec *IPRecord, newRec *IPRecord) bool {
  41. if newRec == nil {
  42. return false
  43. }
  44. if baseRec == nil {
  45. return true
  46. }
  47. return baseRec.Expire.Before(newRec.Expire)
  48. }
  49. var (
  50. errRecordNotFound = errors.New("record not found")
  51. )
  52. type dnsRequest struct {
  53. reqType dnsmessage.Type
  54. domain string
  55. start time.Time
  56. expire time.Time
  57. msg *dnsmessage.Message
  58. }
  59. func genEDNS0Options(clientIP net.IP) *dnsmessage.Resource {
  60. if len(clientIP) == 0 {
  61. return nil
  62. }
  63. var netmask int
  64. var family uint16
  65. if len(clientIP) == 4 {
  66. family = 1
  67. netmask = 24 // 24 for IPV4, 96 for IPv6
  68. } else {
  69. family = 2
  70. netmask = 96
  71. }
  72. b := make([]byte, 4)
  73. binary.BigEndian.PutUint16(b[0:], family)
  74. b[2] = byte(netmask)
  75. b[3] = 0
  76. switch family {
  77. case 1:
  78. ip := clientIP.To4().Mask(net.CIDRMask(netmask, net.IPv4len*8))
  79. needLength := (netmask + 8 - 1) / 8 // division rounding up
  80. b = append(b, ip[:needLength]...)
  81. case 2:
  82. ip := clientIP.Mask(net.CIDRMask(netmask, net.IPv6len*8))
  83. needLength := (netmask + 8 - 1) / 8 // division rounding up
  84. b = append(b, ip[:needLength]...)
  85. }
  86. const EDNS0SUBNET = 0x08
  87. opt := new(dnsmessage.Resource)
  88. common.Must(opt.Header.SetEDNS0(1350, 0xfe00, true))
  89. opt.Body = &dnsmessage.OPTResource{
  90. Options: []dnsmessage.Option{
  91. {
  92. Code: EDNS0SUBNET,
  93. Data: b,
  94. },
  95. },
  96. }
  97. return opt
  98. }
  99. func buildReqMsgs(domain string, option dns_feature.IPOption, reqIDGen func() uint16, reqOpts *dnsmessage.Resource) []*dnsRequest {
  100. qA := dnsmessage.Question{
  101. Name: dnsmessage.MustNewName(domain),
  102. Type: dnsmessage.TypeA,
  103. Class: dnsmessage.ClassINET,
  104. }
  105. qAAAA := dnsmessage.Question{
  106. Name: dnsmessage.MustNewName(domain),
  107. Type: dnsmessage.TypeAAAA,
  108. Class: dnsmessage.ClassINET,
  109. }
  110. var reqs []*dnsRequest
  111. now := time.Now()
  112. if option.IPv4Enable {
  113. msg := new(dnsmessage.Message)
  114. msg.Header.ID = reqIDGen()
  115. msg.Header.RecursionDesired = true
  116. msg.Questions = []dnsmessage.Question{qA}
  117. if reqOpts != nil {
  118. msg.Additionals = append(msg.Additionals, *reqOpts)
  119. }
  120. reqs = append(reqs, &dnsRequest{
  121. reqType: dnsmessage.TypeA,
  122. domain: domain,
  123. start: now,
  124. msg: msg,
  125. })
  126. }
  127. if option.IPv6Enable {
  128. msg := new(dnsmessage.Message)
  129. msg.Header.ID = reqIDGen()
  130. msg.Header.RecursionDesired = true
  131. msg.Questions = []dnsmessage.Question{qAAAA}
  132. if reqOpts != nil {
  133. msg.Additionals = append(msg.Additionals, *reqOpts)
  134. }
  135. reqs = append(reqs, &dnsRequest{
  136. reqType: dnsmessage.TypeAAAA,
  137. domain: domain,
  138. start: now,
  139. msg: msg,
  140. })
  141. }
  142. return reqs
  143. }
  144. // parseResponse parse DNS answers from the returned payload
  145. func parseResponse(payload []byte) (*IPRecord, error) {
  146. var parser dnsmessage.Parser
  147. h, err := parser.Start(payload)
  148. if err != nil {
  149. return nil, newError("failed to parse DNS response").Base(err).AtWarning()
  150. }
  151. if err := parser.SkipAllQuestions(); err != nil {
  152. return nil, newError("failed to skip questions in DNS response").Base(err).AtWarning()
  153. }
  154. now := time.Now()
  155. ipRecord := &IPRecord{
  156. ReqID: h.ID,
  157. RCode: h.RCode,
  158. Expire: now.Add(time.Second * 600),
  159. }
  160. L:
  161. for {
  162. ah, err := parser.AnswerHeader()
  163. if err != nil {
  164. if err != dnsmessage.ErrSectionDone {
  165. newError("failed to parse answer section for domain: ", ah.Name.String()).Base(err).WriteToLog()
  166. }
  167. break
  168. }
  169. ttl := ah.TTL
  170. if ttl == 0 {
  171. ttl = 600
  172. }
  173. expire := now.Add(time.Duration(ttl) * time.Second)
  174. if ipRecord.Expire.After(expire) {
  175. ipRecord.Expire = expire
  176. }
  177. switch ah.Type {
  178. case dnsmessage.TypeA:
  179. ans, err := parser.AResource()
  180. if err != nil {
  181. newError("failed to parse A record for domain: ", ah.Name).Base(err).WriteToLog()
  182. break L
  183. }
  184. ipRecord.IP = append(ipRecord.IP, net.IPAddress(ans.A[:]))
  185. case dnsmessage.TypeAAAA:
  186. ans, err := parser.AAAAResource()
  187. if err != nil {
  188. newError("failed to parse A record for domain: ", ah.Name).Base(err).WriteToLog()
  189. break L
  190. }
  191. ipRecord.IP = append(ipRecord.IP, net.IPAddress(ans.AAAA[:]))
  192. default:
  193. if err := parser.SkipAnswer(); err != nil {
  194. newError("failed to skip answer").Base(err).WriteToLog()
  195. break L
  196. }
  197. continue
  198. }
  199. }
  200. return ipRecord, nil
  201. }