config.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package router
  2. import (
  3. "context"
  4. "regexp"
  5. "strings"
  6. "github.com/xtls/xray-core/common/errors"
  7. "github.com/xtls/xray-core/features/outbound"
  8. "github.com/xtls/xray-core/features/routing"
  9. )
  10. type Rule struct {
  11. Tag string
  12. RuleTag string
  13. Balancer *Balancer
  14. Condition Condition
  15. }
  16. func (r *Rule) GetTag() (string, error) {
  17. if r.Balancer != nil {
  18. return r.Balancer.PickOutbound()
  19. }
  20. return r.Tag, nil
  21. }
  22. // Apply checks rule matching of current routing context.
  23. func (r *Rule) Apply(ctx routing.Context) bool {
  24. return r.Condition.Apply(ctx)
  25. }
  26. func (rr *RoutingRule) BuildCondition() (Condition, error) {
  27. conds := NewConditionChan()
  28. if len(rr.Domain) > 0 {
  29. matcher, err := NewMphMatcherGroup(rr.Domain)
  30. if err != nil {
  31. return nil, errors.New("failed to build domain condition with MphDomainMatcher").Base(err)
  32. }
  33. errors.LogDebug(context.Background(), "MphDomainMatcher is enabled for ", len(rr.Domain), " domain rule(s)")
  34. conds.Add(matcher)
  35. }
  36. if len(rr.UserEmail) > 0 {
  37. conds.Add(NewUserMatcher(rr.UserEmail))
  38. }
  39. if rr.VlessRouteList != nil {
  40. conds.Add(NewPortMatcher(rr.VlessRouteList, "vlessRoute"))
  41. }
  42. if len(rr.InboundTag) > 0 {
  43. conds.Add(NewInboundTagMatcher(rr.InboundTag))
  44. }
  45. if rr.PortList != nil {
  46. conds.Add(NewPortMatcher(rr.PortList, "target"))
  47. }
  48. if rr.SourcePortList != nil {
  49. conds.Add(NewPortMatcher(rr.SourcePortList, "source"))
  50. }
  51. if rr.LocalPortList != nil {
  52. conds.Add(NewPortMatcher(rr.LocalPortList, "local"))
  53. }
  54. if len(rr.Networks) > 0 {
  55. conds.Add(NewNetworkMatcher(rr.Networks))
  56. }
  57. if len(rr.Geoip) > 0 {
  58. cond, err := NewMultiGeoIPMatcher(rr.Geoip, "target")
  59. if err != nil {
  60. return nil, err
  61. }
  62. conds.Add(cond)
  63. }
  64. if len(rr.SourceGeoip) > 0 {
  65. cond, err := NewMultiGeoIPMatcher(rr.SourceGeoip, "source")
  66. if err != nil {
  67. return nil, err
  68. }
  69. conds.Add(cond)
  70. }
  71. if len(rr.LocalGeoip) > 0 {
  72. cond, err := NewMultiGeoIPMatcher(rr.LocalGeoip, "local")
  73. if err != nil {
  74. return nil, err
  75. }
  76. conds.Add(cond)
  77. errors.LogWarning(context.Background(), "Due to some limitations, in UDP connections, localIP is always equal to listen interface IP, so \"localIP\" rule condition does not work properly on UDP inbound connections that listen on all interfaces")
  78. }
  79. if len(rr.Protocol) > 0 {
  80. conds.Add(NewProtocolMatcher(rr.Protocol))
  81. }
  82. if len(rr.Attributes) > 0 {
  83. configuredKeys := make(map[string]*regexp.Regexp)
  84. for key, value := range rr.Attributes {
  85. configuredKeys[strings.ToLower(key)] = regexp.MustCompile(value)
  86. }
  87. conds.Add(&AttributeMatcher{configuredKeys})
  88. }
  89. if conds.Len() == 0 {
  90. return nil, errors.New("this rule has no effective fields").AtWarning()
  91. }
  92. return conds, nil
  93. }
  94. // Build builds the balancing rule
  95. func (br *BalancingRule) Build(ohm outbound.Manager, dispatcher routing.Dispatcher) (*Balancer, error) {
  96. switch strings.ToLower(br.Strategy) {
  97. case "leastping":
  98. return &Balancer{
  99. selectors: br.OutboundSelector,
  100. strategy: &LeastPingStrategy{},
  101. fallbackTag: br.FallbackTag,
  102. ohm: ohm,
  103. }, nil
  104. case "roundrobin":
  105. return &Balancer{
  106. selectors: br.OutboundSelector,
  107. strategy: &RoundRobinStrategy{FallbackTag: br.FallbackTag},
  108. fallbackTag: br.FallbackTag,
  109. ohm: ohm,
  110. }, nil
  111. case "leastload":
  112. i, err := br.StrategySettings.GetInstance()
  113. if err != nil {
  114. return nil, err
  115. }
  116. s, ok := i.(*StrategyLeastLoadConfig)
  117. if !ok {
  118. return nil, errors.New("not a StrategyLeastLoadConfig").AtError()
  119. }
  120. leastLoadStrategy := NewLeastLoadStrategy(s)
  121. return &Balancer{
  122. selectors: br.OutboundSelector,
  123. ohm: ohm,
  124. fallbackTag: br.FallbackTag,
  125. strategy: leastLoadStrategy,
  126. }, nil
  127. case "random":
  128. fallthrough
  129. case "":
  130. return &Balancer{
  131. selectors: br.OutboundSelector,
  132. ohm: ohm,
  133. fallbackTag: br.FallbackTag,
  134. strategy: &RandomStrategy{FallbackTag: br.FallbackTag},
  135. }, nil
  136. default:
  137. return nil, errors.New("unrecognized balancer type")
  138. }
  139. }