1
0

router.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. package router
  2. //go:generate go run github.com/xtls/xray-core/common/errors/errorgen
  3. import (
  4. "context"
  5. sync "sync"
  6. "github.com/xtls/xray-core/common"
  7. "github.com/xtls/xray-core/common/serial"
  8. "github.com/xtls/xray-core/core"
  9. "github.com/xtls/xray-core/features/dns"
  10. "github.com/xtls/xray-core/features/outbound"
  11. "github.com/xtls/xray-core/features/routing"
  12. routing_dns "github.com/xtls/xray-core/features/routing/dns"
  13. )
  14. // Router is an implementation of routing.Router.
  15. type Router struct {
  16. domainStrategy Config_DomainStrategy
  17. rules []*Rule
  18. balancers map[string]*Balancer
  19. dns dns.Client
  20. ctx context.Context
  21. ohm outbound.Manager
  22. dispatcher routing.Dispatcher
  23. mu sync.Mutex
  24. }
  25. // Route is an implementation of routing.Route.
  26. type Route struct {
  27. routing.Context
  28. outboundGroupTags []string
  29. outboundTag string
  30. }
  31. // Init initializes the Router.
  32. func (r *Router) Init(ctx context.Context, config *Config, d dns.Client, ohm outbound.Manager, dispatcher routing.Dispatcher) error {
  33. r.domainStrategy = config.DomainStrategy
  34. r.dns = d
  35. r.ctx = ctx
  36. r.ohm = ohm
  37. r.dispatcher = dispatcher
  38. r.balancers = make(map[string]*Balancer, len(config.BalancingRule))
  39. for _, rule := range config.BalancingRule {
  40. balancer, err := rule.Build(ohm, dispatcher)
  41. if err != nil {
  42. return err
  43. }
  44. balancer.InjectContext(ctx)
  45. r.balancers[rule.Tag] = balancer
  46. }
  47. r.rules = make([]*Rule, 0, len(config.Rule))
  48. for _, rule := range config.Rule {
  49. cond, err := rule.BuildCondition()
  50. if err != nil {
  51. return err
  52. }
  53. rr := &Rule{
  54. Condition: cond,
  55. Tag: rule.GetTag(),
  56. RuleTag: rule.GetRuleTag(),
  57. }
  58. btag := rule.GetBalancingTag()
  59. if len(btag) > 0 {
  60. brule, found := r.balancers[btag]
  61. if !found {
  62. return newError("balancer ", btag, " not found")
  63. }
  64. rr.Balancer = brule
  65. }
  66. r.rules = append(r.rules, rr)
  67. }
  68. return nil
  69. }
  70. // PickRoute implements routing.Router.
  71. func (r *Router) PickRoute(ctx routing.Context) (routing.Route, error) {
  72. rule, ctx, err := r.pickRouteInternal(ctx)
  73. if err != nil {
  74. return nil, err
  75. }
  76. tag, err := rule.GetTag()
  77. if err != nil {
  78. return nil, err
  79. }
  80. return &Route{Context: ctx, outboundTag: tag}, nil
  81. }
  82. // AddRule implements routing.Router.
  83. func (r *Router) AddRule(config *serial.TypedMessage, shouldAppend bool) error {
  84. inst, err := config.GetInstance()
  85. if err != nil {
  86. return err
  87. }
  88. if c, ok := inst.(*Config); ok {
  89. return r.ReloadRules(c, shouldAppend)
  90. }
  91. return newError("AddRule: config type error")
  92. }
  93. func (r *Router) ReloadRules(config *Config, shouldAppend bool) error {
  94. r.mu.Lock()
  95. defer r.mu.Unlock()
  96. if !shouldAppend {
  97. r.balancers = make(map[string]*Balancer, len(config.BalancingRule))
  98. r.rules = make([]*Rule, 0, len(config.Rule))
  99. }
  100. for _, rule := range config.BalancingRule {
  101. _, found := r.balancers[rule.Tag]
  102. if found {
  103. return newError("duplicate balancer tag")
  104. }
  105. balancer, err := rule.Build(r.ohm, r.dispatcher)
  106. if err != nil {
  107. return err
  108. }
  109. balancer.InjectContext(r.ctx)
  110. r.balancers[rule.Tag] = balancer
  111. }
  112. for _, rule := range config.Rule {
  113. if r.RuleExists(rule.GetRuleTag()) {
  114. return newError("duplicate ruleTag ", rule.GetRuleTag())
  115. }
  116. cond, err := rule.BuildCondition()
  117. if err != nil {
  118. return err
  119. }
  120. rr := &Rule{
  121. Condition: cond,
  122. Tag: rule.GetTag(),
  123. RuleTag: rule.GetRuleTag(),
  124. }
  125. btag := rule.GetBalancingTag()
  126. if len(btag) > 0 {
  127. brule, found := r.balancers[btag]
  128. if !found {
  129. return newError("balancer ", btag, " not found")
  130. }
  131. rr.Balancer = brule
  132. }
  133. r.rules = append(r.rules, rr)
  134. }
  135. return nil
  136. }
  137. func (r *Router) RuleExists(tag string) bool {
  138. if tag != "" {
  139. for _, rule := range r.rules {
  140. if rule.RuleTag == tag {
  141. return true
  142. }
  143. }
  144. }
  145. return false
  146. }
  147. // RemoveRule implements routing.Router.
  148. func (r *Router) RemoveRule(tag string) error {
  149. r.mu.Lock()
  150. defer r.mu.Unlock()
  151. newRules := []*Rule{}
  152. if tag != "" {
  153. for _, rule := range r.rules {
  154. if rule.RuleTag != tag {
  155. newRules = append(newRules, rule)
  156. }
  157. }
  158. r.rules = newRules
  159. return nil
  160. }
  161. return newError("empty tag name!")
  162. }
  163. func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routing.Context, error) {
  164. // SkipDNSResolve is set from DNS module.
  165. // the DOH remote server maybe a domain name,
  166. // this prevents cycle resolving dead loop
  167. skipDNSResolve := ctx.GetSkipDNSResolve()
  168. if r.domainStrategy == Config_IpOnDemand && !skipDNSResolve {
  169. ctx = routing_dns.ContextWithDNSClient(ctx, r.dns)
  170. }
  171. for _, rule := range r.rules {
  172. if rule.Apply(ctx) {
  173. return rule, ctx, nil
  174. }
  175. }
  176. if r.domainStrategy != Config_IpIfNonMatch || len(ctx.GetTargetDomain()) == 0 || skipDNSResolve {
  177. return nil, ctx, common.ErrNoClue
  178. }
  179. ctx = routing_dns.ContextWithDNSClient(ctx, r.dns)
  180. // Try applying rules again if we have IPs.
  181. for _, rule := range r.rules {
  182. if rule.Apply(ctx) {
  183. return rule, ctx, nil
  184. }
  185. }
  186. return nil, ctx, common.ErrNoClue
  187. }
  188. // Start implements common.Runnable.
  189. func (r *Router) Start() error {
  190. return nil
  191. }
  192. // Close implements common.Closable.
  193. func (r *Router) Close() error {
  194. return nil
  195. }
  196. // Type implements common.HasType.
  197. func (*Router) Type() interface{} {
  198. return routing.RouterType()
  199. }
  200. // GetOutboundGroupTags implements routing.Route.
  201. func (r *Route) GetOutboundGroupTags() []string {
  202. return r.outboundGroupTags
  203. }
  204. // GetOutboundTag implements routing.Route.
  205. func (r *Route) GetOutboundTag() string {
  206. return r.outboundTag
  207. }
  208. func init() {
  209. common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
  210. r := new(Router)
  211. if err := core.RequireFeatures(ctx, func(d dns.Client, ohm outbound.Manager, dispatcher routing.Dispatcher) error {
  212. return r.Init(ctx, config.(*Config), d, ohm, dispatcher)
  213. }); err != nil {
  214. return nil, err
  215. }
  216. return r, nil
  217. }))
  218. }