nameserver.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. package dns
  2. import (
  3. "context"
  4. "net/url"
  5. "strings"
  6. "time"
  7. core "github.com/v2fly/v2ray-core/v5"
  8. "github.com/v2fly/v2ray-core/v5/app/dns/fakedns"
  9. "github.com/v2fly/v2ray-core/v5/app/router"
  10. "github.com/v2fly/v2ray-core/v5/common/errors"
  11. "github.com/v2fly/v2ray-core/v5/common/net"
  12. "github.com/v2fly/v2ray-core/v5/common/session"
  13. "github.com/v2fly/v2ray-core/v5/features"
  14. "github.com/v2fly/v2ray-core/v5/features/dns"
  15. "github.com/v2fly/v2ray-core/v5/features/routing"
  16. )
  17. // Server is the interface for Name Server.
  18. type Server interface {
  19. // Name of the Client.
  20. Name() string
  21. // QueryIP sends IP queries to its configured server.
  22. QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns.IPOption, disableCache bool) ([]net.IP, error)
  23. }
  24. // Client is the interface for DNS client.
  25. type Client struct {
  26. server Server
  27. clientIP net.IP
  28. tag string
  29. queryStrategy dns.IPOption
  30. cacheStrategy CacheStrategy
  31. fallbackStrategy FallbackStrategy
  32. domains []string
  33. expectIPs []*router.GeoIPMatcher
  34. fakeDNS Server
  35. }
  36. var errExpectedIPNonMatch = errors.New("expectIPs not match")
  37. // NewServer creates a name server object according to the network destination url.
  38. func NewServer(ctx context.Context, dest net.Destination, onCreated func(Server) error) error {
  39. onCreatedWithError := func(server Server, err error) error {
  40. if err != nil {
  41. return err
  42. }
  43. return onCreated(server)
  44. }
  45. if address := dest.Address; address.Family().IsDomain() {
  46. u, err := url.Parse(address.Domain())
  47. if err != nil {
  48. return err
  49. }
  50. switch {
  51. case strings.EqualFold(u.String(), "localhost"):
  52. return onCreated(NewLocalNameServer())
  53. case strings.EqualFold(u.String(), "fakedns"):
  54. return core.RequireFeatures(ctx, func(fakedns dns.FakeDNSEngine) error { return onCreated(NewFakeDNSServer(fakedns)) })
  55. case strings.EqualFold(u.Scheme, "https"): // DOH Remote mode
  56. return core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error { return onCreatedWithError(NewDoHNameServer(u, dispatcher)) })
  57. case strings.EqualFold(u.Scheme, "https+local"): // DOH Local mode
  58. return onCreated(NewDoHLocalNameServer(u))
  59. case strings.EqualFold(u.Scheme, "tcp"): // DNS-over-TCP Remote mode
  60. return core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error { return onCreatedWithError(NewTCPNameServer(u, dispatcher)) })
  61. case strings.EqualFold(u.Scheme, "tcp+local"): // DNS-over-TCP Local mode
  62. return onCreatedWithError(NewTCPLocalNameServer(u))
  63. case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode
  64. return onCreatedWithError(NewQUICNameServer(u))
  65. }
  66. }
  67. if dest.Network == net.Network_Unknown {
  68. dest.Network = net.Network_UDP
  69. }
  70. if dest.Network == net.Network_UDP { // UDP classic DNS mode
  71. return core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error { return onCreated(NewClassicNameServer(dest, dispatcher)) })
  72. }
  73. return newError("No available name server could be created from ", dest).AtWarning()
  74. }
  75. // NewClient creates a DNS client managing a name server with client IP, domain rules and expected IPs.
  76. func NewClient(ctx context.Context, ns *NameServer, dns *Config) (*Client, error) {
  77. client := &Client{}
  78. // Create DNS server instance
  79. err := NewServer(ctx, ns.Address.AsDestination(), func(server Server) error {
  80. client.server = server
  81. return nil
  82. })
  83. if err != nil {
  84. return nil, err
  85. }
  86. // Initialize fields with default values
  87. if len(ns.Tag) == 0 {
  88. ns.Tag = dns.Tag
  89. if len(ns.Tag) == 0 {
  90. ns.Tag = generateRandomTag()
  91. }
  92. }
  93. if len(ns.ClientIp) == 0 {
  94. ns.ClientIp = dns.ClientIp
  95. }
  96. if ns.QueryStrategy == nil {
  97. ns.QueryStrategy = &dns.QueryStrategy
  98. }
  99. if ns.CacheStrategy == nil {
  100. ns.CacheStrategy = new(CacheStrategy)
  101. switch {
  102. case dns.CacheStrategy != CacheStrategy_CacheEnabled:
  103. *ns.CacheStrategy = dns.CacheStrategy
  104. case dns.DisableCache:
  105. features.PrintDeprecatedFeatureWarning("DNS disableCache settings")
  106. *ns.CacheStrategy = CacheStrategy_CacheDisabled
  107. }
  108. }
  109. if ns.FallbackStrategy == nil {
  110. ns.FallbackStrategy = new(FallbackStrategy)
  111. switch {
  112. case ns.SkipFallback:
  113. features.PrintDeprecatedFeatureWarning("DNS server skipFallback settings")
  114. *ns.FallbackStrategy = FallbackStrategy_Disabled
  115. case dns.FallbackStrategy != FallbackStrategy_Enabled:
  116. *ns.FallbackStrategy = dns.FallbackStrategy
  117. case dns.DisableFallback:
  118. features.PrintDeprecatedFeatureWarning("DNS disableFallback settings")
  119. *ns.FallbackStrategy = FallbackStrategy_Disabled
  120. case dns.DisableFallbackIfMatch:
  121. features.PrintDeprecatedFeatureWarning("DNS disableFallbackIfMatch settings")
  122. *ns.FallbackStrategy = FallbackStrategy_DisabledIfAnyMatch
  123. }
  124. }
  125. if (ns.FakeDns != nil && len(ns.FakeDns.Pools) == 0) || // Use globally configured fake ip pool if: 1. `fakedns` config is set, but empty(represents { "fakedns": true } in JSON settings);
  126. ns.FakeDns == nil && strings.EqualFold(ns.Address.Address.GetDomain(), "fakedns") { // 2. `fakedns` config not set, but server address is `fakedns`(represents { "address": "fakedns" } in JSON settings).
  127. if dns.FakeDns != nil {
  128. ns.FakeDns = dns.FakeDns
  129. } else {
  130. ns.FakeDns = &fakedns.FakeDnsPoolMulti{}
  131. queryStrategy := toIPOption(*ns.QueryStrategy)
  132. if queryStrategy.IPv4Enable {
  133. ns.FakeDns.Pools = append(ns.FakeDns.Pools, &fakedns.FakeDnsPool{
  134. IpPool: "198.18.0.0/15",
  135. LruSize: 65535,
  136. })
  137. }
  138. if queryStrategy.IPv6Enable {
  139. ns.FakeDns.Pools = append(ns.FakeDns.Pools, &fakedns.FakeDnsPool{
  140. IpPool: "fc00::/18",
  141. LruSize: 65535,
  142. })
  143. }
  144. }
  145. }
  146. // Priotize local domains with specific TLDs or without any dot to local DNS
  147. if strings.EqualFold(ns.Address.Address.GetDomain(), "localhost") {
  148. ns.PrioritizedDomain = append(ns.PrioritizedDomain, localTLDsAndDotlessDomains...)
  149. ns.OriginalRules = append(ns.OriginalRules, localTLDsAndDotlessDomainsRule)
  150. }
  151. if len(ns.ClientIp) > 0 {
  152. newError("DNS: client ", ns.Address.Address.AsAddress(), " uses clientIP ", net.IP(ns.ClientIp).String()).AtInfo().WriteToLog()
  153. }
  154. client.clientIP = ns.ClientIp
  155. client.tag = ns.Tag
  156. client.queryStrategy = toIPOption(*ns.QueryStrategy)
  157. client.cacheStrategy = *ns.CacheStrategy
  158. client.fallbackStrategy = *ns.FallbackStrategy
  159. return client, nil
  160. }
  161. // Name returns the server name the client manages.
  162. func (c *Client) Name() string {
  163. return c.server.Name()
  164. }
  165. // QueryIP send DNS query to the name server with the client's IP and IP options.
  166. func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, error) {
  167. queryOption := option.With(c.queryStrategy)
  168. if !queryOption.IsValid() {
  169. newError(c.server.Name(), " returns empty answer: ", domain, ". ", toReqTypes(option)).AtInfo().WriteToLog()
  170. return nil, dns.ErrEmptyResponse
  171. }
  172. server := c.server
  173. if queryOption.FakeEnable && c.fakeDNS != nil {
  174. server = c.fakeDNS
  175. }
  176. disableCache := c.cacheStrategy == CacheStrategy_CacheDisabled
  177. ctx = session.ContextWithInbound(ctx, &session.Inbound{Tag: c.tag})
  178. ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
  179. ips, err := server.QueryIP(ctx, domain, c.clientIP, queryOption, disableCache)
  180. cancel()
  181. if err != nil || queryOption.FakeEnable {
  182. return ips, err
  183. }
  184. return c.MatchExpectedIPs(domain, ips)
  185. }
  186. // MatchExpectedIPs matches queried domain IPs with expected IPs and returns matched ones.
  187. func (c *Client) MatchExpectedIPs(domain string, ips []net.IP) ([]net.IP, error) {
  188. if len(c.expectIPs) == 0 {
  189. return ips, nil
  190. }
  191. newIps := []net.IP{}
  192. for _, ip := range ips {
  193. for _, matcher := range c.expectIPs {
  194. if matcher.Match(ip) {
  195. newIps = append(newIps, ip)
  196. break
  197. }
  198. }
  199. }
  200. if len(newIps) == 0 {
  201. return nil, errExpectedIPNonMatch
  202. }
  203. newError("domain ", domain, " expectIPs ", newIps, " matched at server ", c.Name()).AtDebug().WriteToLog()
  204. return newIps, nil
  205. }