server.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. // +build !confonly
  2. package dns
  3. //go:generate errorgen
  4. import (
  5. "context"
  6. "sync"
  7. "time"
  8. "v2ray.com/core"
  9. "v2ray.com/core/app/router"
  10. "v2ray.com/core/common"
  11. "v2ray.com/core/common/net"
  12. "v2ray.com/core/common/session"
  13. "v2ray.com/core/common/strmatcher"
  14. "v2ray.com/core/common/uuid"
  15. "v2ray.com/core/features"
  16. "v2ray.com/core/features/dns"
  17. "v2ray.com/core/features/routing"
  18. )
  19. // Server is a DNS rely server.
  20. type Server struct {
  21. sync.Mutex
  22. hosts *StaticHosts
  23. clients []Client
  24. clientIP net.IP
  25. domainMatcher strmatcher.IndexMatcher
  26. domainIndexMap map[uint32]uint32
  27. ipIndexMap map[uint32]*MultiGeoIPMatcher
  28. tag string
  29. }
  30. // MultiGeoIPMatcher for match
  31. type MultiGeoIPMatcher struct {
  32. matchers []*router.GeoIPMatcher
  33. }
  34. // Match for
  35. func (c *MultiGeoIPMatcher) Match(ip net.IP) bool {
  36. for _, matcher := range c.matchers {
  37. if matcher.Match(ip) {
  38. return true
  39. }
  40. }
  41. return false
  42. }
  43. // HasMatcher f
  44. func (c *MultiGeoIPMatcher) HasMatcher() bool {
  45. if len(c.matchers) > 0 {
  46. return true
  47. }
  48. return false
  49. }
  50. func generateRandomTag() string {
  51. id := uuid.New()
  52. return "v2ray.system." + id.String()
  53. }
  54. // New creates a new DNS server with given configuration.
  55. func New(ctx context.Context, config *Config) (*Server, error) {
  56. server := &Server{
  57. clients: make([]Client, 0, len(config.NameServers)+len(config.NameServer)),
  58. tag: config.Tag,
  59. }
  60. if server.tag == "" {
  61. server.tag = generateRandomTag()
  62. }
  63. if len(config.ClientIp) > 0 {
  64. if len(config.ClientIp) != 4 && len(config.ClientIp) != 16 {
  65. return nil, newError("unexpected IP length", len(config.ClientIp))
  66. }
  67. server.clientIP = net.IP(config.ClientIp)
  68. }
  69. hosts, err := NewStaticHosts(config.StaticHosts, config.Hosts)
  70. if err != nil {
  71. return nil, newError("failed to create hosts").Base(err)
  72. }
  73. server.hosts = hosts
  74. addNameServer := func(endpoint *net.Endpoint) int {
  75. address := endpoint.Address.AsAddress()
  76. if address.Family().IsDomain() && address.Domain() == "localhost" {
  77. server.clients = append(server.clients, NewLocalNameServer())
  78. } else {
  79. dest := endpoint.AsDestination()
  80. if dest.Network == net.Network_Unknown {
  81. dest.Network = net.Network_UDP
  82. }
  83. if dest.Network == net.Network_UDP {
  84. idx := len(server.clients)
  85. server.clients = append(server.clients, nil)
  86. common.Must(core.RequireFeatures(ctx, func(d routing.Dispatcher) {
  87. server.clients[idx] = NewClassicNameServer(dest, d, server.clientIP)
  88. }))
  89. }
  90. }
  91. return len(server.clients) - 1
  92. }
  93. if len(config.NameServers) > 0 {
  94. features.PrintDeprecatedFeatureWarning("simple DNS server")
  95. }
  96. for _, destPB := range config.NameServers {
  97. addNameServer(destPB)
  98. }
  99. var geoIPMatcherContainer router.GeoIPMatcherContainer
  100. if len(config.NameServer) > 0 {
  101. domainMatcher := &strmatcher.MatcherGroup{}
  102. domainIndexMap := make(map[uint32]uint32)
  103. ipIndexMap := make(map[uint32]*MultiGeoIPMatcher)
  104. for _, ns := range config.NameServer {
  105. idx := addNameServer(ns.Address)
  106. for _, domain := range ns.PrioritizedDomain {
  107. matcher, err := toStrMatcher(domain.Type, domain.Domain)
  108. if err != nil {
  109. return nil, newError("failed to create prioritized domain").Base(err).AtWarning()
  110. }
  111. midx := domainMatcher.Add(matcher)
  112. domainIndexMap[midx] = uint32(idx)
  113. }
  114. var matchers []*router.GeoIPMatcher
  115. for _, geoip := range ns.Geoip {
  116. matcher, err := geoIPMatcherContainer.Add(geoip)
  117. if err != nil {
  118. return nil, newError("failed to create ip matcher").Base(err).AtWarning()
  119. }
  120. matchers = append(matchers, matcher)
  121. }
  122. matcher := &MultiGeoIPMatcher{matchers: matchers}
  123. ipIndexMap[uint32(idx)] = matcher
  124. }
  125. server.domainMatcher = domainMatcher
  126. server.domainIndexMap = domainIndexMap
  127. server.ipIndexMap = ipIndexMap
  128. }
  129. if len(server.clients) == 0 {
  130. server.clients = append(server.clients, NewLocalNameServer())
  131. }
  132. return server, nil
  133. }
  134. // Type implements common.HasType.
  135. func (*Server) Type() interface{} {
  136. return dns.ClientType()
  137. }
  138. // Start implements common.Runnable.
  139. func (s *Server) Start() error {
  140. return nil
  141. }
  142. // Close implements common.Closable.
  143. func (s *Server) Close() error {
  144. return nil
  145. }
  146. func (s *Server) IsOwnLink(ctx context.Context) bool {
  147. inbound := session.InboundFromContext(ctx)
  148. return inbound != nil && inbound.Tag == s.tag
  149. }
  150. // Match check dns ip match geoip
  151. func (s *Server) Match(idx uint32, client Client, domain string, ips []net.IP) ([]net.IP, error) {
  152. if len(ips) == 0 {
  153. newError("domain ", domain, " has empty response at server ", client.Name(), " idx:", idx).AtDebug().WriteToLog()
  154. return nil, context.Canceled
  155. }
  156. matcher, exist := s.ipIndexMap[idx]
  157. if exist == false {
  158. newError("domain ", domain, " server not in ipIndexMap: ", client.Name(), " idx:", idx, " just return").AtDebug().WriteToLog()
  159. return ips, nil
  160. }
  161. if matcher.HasMatcher() == false {
  162. newError("domain ", domain, "server has not valid matcher: ", client.Name(), " idx:", idx, " just return").AtDebug().WriteToLog()
  163. return ips, nil
  164. }
  165. newIps := []net.IP{}
  166. for _, ip := range ips {
  167. if matcher.Match(ip) {
  168. newIps = append(newIps, ip)
  169. newError("domain ", domain, " ip ", ip, " is match at server ", client.Name(), " idx:", idx).AtDebug().WriteToLog()
  170. } else {
  171. newError("domain ", domain, " ip ", ip, " is not match at server ", client.Name(), " idx:", idx).AtDebug().WriteToLog()
  172. }
  173. }
  174. if len(newIps) == 0 {
  175. return nil, context.Canceled
  176. }
  177. return newIps, nil
  178. }
  179. func (s *Server) queryIPTimeout(idx uint32, client Client, domain string, option IPOption) ([]net.IP, error) {
  180. ctx, cancel := context.WithTimeout(context.Background(), time.Second*4)
  181. if len(s.tag) > 0 {
  182. ctx = session.ContextWithInbound(ctx, &session.Inbound{
  183. Tag: s.tag,
  184. })
  185. }
  186. ips, err := client.QueryIP(ctx, domain, option)
  187. ips, err = s.Match(idx, client, domain, ips)
  188. cancel()
  189. return ips, err
  190. }
  191. // LookupIP implements dns.Client.
  192. func (s *Server) LookupIP(domain string) ([]net.IP, error) {
  193. return s.lookupIPInternal(domain, IPOption{
  194. IPv4Enable: true,
  195. IPv6Enable: true,
  196. })
  197. }
  198. // LookupIPv4 implements dns.IPv4Lookup.
  199. func (s *Server) LookupIPv4(domain string) ([]net.IP, error) {
  200. return s.lookupIPInternal(domain, IPOption{
  201. IPv4Enable: true,
  202. IPv6Enable: false,
  203. })
  204. }
  205. // LookupIPv6 implements dns.IPv6Lookup.
  206. func (s *Server) LookupIPv6(domain string) ([]net.IP, error) {
  207. return s.lookupIPInternal(domain, IPOption{
  208. IPv4Enable: false,
  209. IPv6Enable: true,
  210. })
  211. }
  212. func (s *Server) lookupStatic(domain string, option IPOption, depth int32) []net.Address {
  213. ips := s.hosts.LookupIP(domain, option)
  214. if ips == nil {
  215. return nil
  216. }
  217. if ips[0].Family().IsDomain() && depth < 5 {
  218. if newIPs := s.lookupStatic(ips[0].Domain(), option, depth+1); newIPs != nil {
  219. return newIPs
  220. }
  221. }
  222. return ips
  223. }
  224. func toNetIP(ips []net.Address) []net.IP {
  225. if len(ips) == 0 {
  226. return nil
  227. }
  228. netips := make([]net.IP, 0, len(ips))
  229. for _, ip := range ips {
  230. netips = append(netips, ip.IP())
  231. }
  232. return netips
  233. }
  234. func (s *Server) lookupIPInternal(domain string, option IPOption) ([]net.IP, error) {
  235. if domain == "" {
  236. return nil, newError("empty domain name")
  237. }
  238. if domain[len(domain)-1] == '.' {
  239. domain = domain[:len(domain)-1]
  240. }
  241. ips := s.lookupStatic(domain, option, 0)
  242. if ips != nil && ips[0].Family().IsIP() {
  243. newError("returning ", len(ips), " IPs for domain ", domain).WriteToLog()
  244. return toNetIP(ips), nil
  245. }
  246. if ips != nil && ips[0].Family().IsDomain() {
  247. newdomain := ips[0].Domain()
  248. newError("domain replaced: ", domain, " -> ", newdomain).WriteToLog()
  249. domain = newdomain
  250. }
  251. var lastErr error
  252. if s.domainMatcher != nil {
  253. idx := s.domainMatcher.Match(domain)
  254. if idx > 0 {
  255. ns := s.clients[s.domainIndexMap[idx]]
  256. newError("domain matched, direct lookup ip for domain ", domain, " at ", ns.Name()).WriteToLog()
  257. ips, err := s.queryIPTimeout(s.domainIndexMap[idx], ns, domain, option)
  258. if len(ips) > 0 {
  259. return ips, nil
  260. }
  261. if err == dns.ErrEmptyResponse {
  262. return nil, err
  263. }
  264. if err != nil {
  265. newError("failed to lookup ip for domain ", domain, " at server ", ns.Name()).Base(err).WriteToLog()
  266. lastErr = err
  267. }
  268. }
  269. }
  270. for idx, client := range s.clients {
  271. newError("try to lookup ip for domain ", domain, " at server ", client.Name(), " idx:", idx).AtDebug().WriteToLog()
  272. ips, err := s.queryIPTimeout(uint32(idx), client, domain, option)
  273. if len(ips) > 0 {
  274. newError("lookup ip for domain ", domain, " success: ", ips, " at server ", client.Name(), " idx:", idx).AtDebug().WriteToLog()
  275. return ips, nil
  276. }
  277. if err != nil {
  278. newError("failed to lookup ip for domain ", domain, " at server ", client.Name()).Base(err).WriteToLog()
  279. lastErr = err
  280. }
  281. if err != context.Canceled && err != context.DeadlineExceeded {
  282. return nil, err
  283. }
  284. }
  285. return nil, newError("returning nil for domain ", domain).Base(lastErr)
  286. }
  287. func init() {
  288. common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
  289. return New(ctx, config.(*Config))
  290. }))
  291. }