router.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. package router
  2. //go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
  3. import (
  4. "context"
  5. core "github.com/v2fly/v2ray-core/v4"
  6. "github.com/v2fly/v2ray-core/v4/common"
  7. "github.com/v2fly/v2ray-core/v4/common/platform"
  8. "github.com/v2fly/v2ray-core/v4/features/dns"
  9. "github.com/v2fly/v2ray-core/v4/features/outbound"
  10. "github.com/v2fly/v2ray-core/v4/features/routing"
  11. routing_dns "github.com/v2fly/v2ray-core/v4/features/routing/dns"
  12. "github.com/v2fly/v2ray-core/v4/infra/conf/cfgcommon"
  13. "github.com/v2fly/v2ray-core/v4/infra/conf/geodata"
  14. )
  15. // Router is an implementation of routing.Router.
  16. type Router struct {
  17. domainStrategy DomainStrategy
  18. rules []*Rule
  19. balancers map[string]*Balancer
  20. dns dns.Client
  21. }
  22. // Route is an implementation of routing.Route.
  23. type Route struct {
  24. routing.Context
  25. outboundGroupTags []string
  26. outboundTag string
  27. }
  28. // Init initializes the Router.
  29. func (r *Router) Init(ctx context.Context, config *Config, d dns.Client, ohm outbound.Manager, dispatcher routing.Dispatcher) error {
  30. r.domainStrategy = config.DomainStrategy
  31. r.dns = d
  32. r.balancers = make(map[string]*Balancer, len(config.BalancingRule))
  33. for _, rule := range config.BalancingRule {
  34. balancer, err := rule.Build(ohm, dispatcher)
  35. if err != nil {
  36. return err
  37. }
  38. balancer.InjectContext(ctx)
  39. r.balancers[rule.Tag] = balancer
  40. }
  41. r.rules = make([]*Rule, 0, len(config.Rule))
  42. for _, rule := range config.Rule {
  43. cond, err := rule.BuildCondition()
  44. if err != nil {
  45. return err
  46. }
  47. rr := &Rule{
  48. Condition: cond,
  49. Tag: rule.GetTag(),
  50. }
  51. btag := rule.GetBalancingTag()
  52. if len(btag) > 0 {
  53. brule, found := r.balancers[btag]
  54. if !found {
  55. return newError("balancer ", btag, " not found")
  56. }
  57. rr.Balancer = brule
  58. }
  59. r.rules = append(r.rules, rr)
  60. }
  61. return nil
  62. }
  63. // PickRoute implements routing.Router.
  64. func (r *Router) PickRoute(ctx routing.Context) (routing.Route, error) {
  65. rule, ctx, err := r.pickRouteInternal(ctx)
  66. if err != nil {
  67. return nil, err
  68. }
  69. tag, err := rule.GetTag()
  70. if err != nil {
  71. return nil, err
  72. }
  73. return &Route{Context: ctx, outboundTag: tag}, nil
  74. }
  75. func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routing.Context, error) {
  76. // SkipDNSResolve is set from DNS module.
  77. // the DOH remote server maybe a domain name,
  78. // this prevents cycle resolving dead loop
  79. skipDNSResolve := ctx.GetSkipDNSResolve()
  80. if r.domainStrategy == DomainStrategy_IpOnDemand && !skipDNSResolve {
  81. ctx = routing_dns.ContextWithDNSClient(ctx, r.dns)
  82. }
  83. for _, rule := range r.rules {
  84. if rule.Apply(ctx) {
  85. return rule, ctx, nil
  86. }
  87. }
  88. if r.domainStrategy != DomainStrategy_IpIfNonMatch || len(ctx.GetTargetDomain()) == 0 || skipDNSResolve {
  89. return nil, ctx, common.ErrNoClue
  90. }
  91. ctx = routing_dns.ContextWithDNSClient(ctx, r.dns)
  92. // Try applying rules again if we have IPs.
  93. for _, rule := range r.rules {
  94. if rule.Apply(ctx) {
  95. return rule, ctx, nil
  96. }
  97. }
  98. return nil, ctx, common.ErrNoClue
  99. }
  100. // Start implements common.Runnable.
  101. func (r *Router) Start() error {
  102. return nil
  103. }
  104. // Close implements common.Closable.
  105. func (r *Router) Close() error {
  106. return nil
  107. }
  108. // Type implement common.HasType.
  109. func (*Router) Type() interface{} {
  110. return routing.RouterType()
  111. }
  112. // GetOutboundGroupTags implements routing.Route.
  113. func (r *Route) GetOutboundGroupTags() []string {
  114. return r.outboundGroupTags
  115. }
  116. // GetOutboundTag implements routing.Route.
  117. func (r *Route) GetOutboundTag() string {
  118. return r.outboundTag
  119. }
  120. func init() {
  121. common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
  122. r := new(Router)
  123. if err := core.RequireFeatures(ctx, func(d dns.Client, ohm outbound.Manager, dispatcher routing.Dispatcher) error {
  124. return r.Init(ctx, config.(*Config), d, ohm, dispatcher)
  125. }); err != nil {
  126. return nil, err
  127. }
  128. return r, nil
  129. }))
  130. common.Must(common.RegisterConfig((*SimplifiedConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
  131. ctx = cfgcommon.NewConfigureLoadingContext(ctx)
  132. geoloadername := platform.NewEnvFlag("v2ray.conf.geoloader").GetValue(func() string {
  133. return "standard"
  134. })
  135. if loader, err := geodata.GetGeoDataLoader(geoloadername); err == nil {
  136. cfgcommon.SetGeoDataLoader(ctx, loader)
  137. } else {
  138. return nil, newError("unable to create geo data loader ").Base(err)
  139. }
  140. cfgEnv := cfgcommon.GetConfigureLoadingEnvironment(ctx)
  141. geoLoader := cfgEnv.GetGeoLoader()
  142. simplifiedConfig := config.(*SimplifiedConfig)
  143. for _, v := range simplifiedConfig.Rule {
  144. for _, geo := range v.Geoip {
  145. if geo.Code != "" {
  146. filepath := "geoip.dat"
  147. if geo.FilePath != "" {
  148. filepath = geo.FilePath
  149. } else {
  150. geo.CountryCode = geo.Code
  151. }
  152. var err error
  153. geo.Cidr, err = geoLoader.LoadIP(filepath, geo.Code)
  154. if err != nil {
  155. return nil, newError("unable to load geoip").Base(err)
  156. }
  157. }
  158. }
  159. for _, geo := range v.GeoDomain {
  160. if geo.Code != "" {
  161. filepath := "geosite.dat"
  162. if geo.FilePath != "" {
  163. filepath = geo.FilePath
  164. }
  165. var err error
  166. geo.Domain, err = geoLoader.LoadGeoSiteWithAttr(filepath, geo.Code)
  167. if err != nil {
  168. return nil, newError("unable to load geodomain").Base(err)
  169. }
  170. v.Domain = append(v.Domain, geo.Domain...)
  171. }
  172. }
  173. }
  174. fullConfig := &Config{
  175. DomainStrategy: simplifiedConfig.DomainStrategy,
  176. Rule: simplifiedConfig.Rule,
  177. BalancingRule: simplifiedConfig.BalancingRule,
  178. }
  179. return common.CreateObject(ctx, fullConfig)
  180. }))
  181. }