router.go 6.6 KB

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