github.com/EagleQL/Xray-core@v1.4.3/app/router/config.go (about)

     1  package router
     2  
     3  import (
     4  	"github.com/xtls/xray-core/common/net"
     5  	"github.com/xtls/xray-core/features/outbound"
     6  	"github.com/xtls/xray-core/features/routing"
     7  )
     8  
     9  // CIDRList is an alias of []*CIDR to provide sort.Interface.
    10  type CIDRList []*CIDR
    11  
    12  // Len implements sort.Interface.
    13  func (l *CIDRList) Len() int {
    14  	return len(*l)
    15  }
    16  
    17  // Less implements sort.Interface.
    18  func (l *CIDRList) Less(i int, j int) bool {
    19  	ci := (*l)[i]
    20  	cj := (*l)[j]
    21  
    22  	if len(ci.Ip) < len(cj.Ip) {
    23  		return true
    24  	}
    25  
    26  	if len(ci.Ip) > len(cj.Ip) {
    27  		return false
    28  	}
    29  
    30  	for k := 0; k < len(ci.Ip); k++ {
    31  		if ci.Ip[k] < cj.Ip[k] {
    32  			return true
    33  		}
    34  
    35  		if ci.Ip[k] > cj.Ip[k] {
    36  			return false
    37  		}
    38  	}
    39  
    40  	return ci.Prefix < cj.Prefix
    41  }
    42  
    43  // Swap implements sort.Interface.
    44  func (l *CIDRList) Swap(i int, j int) {
    45  	(*l)[i], (*l)[j] = (*l)[j], (*l)[i]
    46  }
    47  
    48  type Rule struct {
    49  	Tag       string
    50  	Balancer  *Balancer
    51  	Condition Condition
    52  }
    53  
    54  func (r *Rule) GetTag() (string, error) {
    55  	if r.Balancer != nil {
    56  		return r.Balancer.PickOutbound()
    57  	}
    58  	return r.Tag, nil
    59  }
    60  
    61  // Apply checks rule matching of current routing context.
    62  func (r *Rule) Apply(ctx routing.Context) bool {
    63  	return r.Condition.Apply(ctx)
    64  }
    65  
    66  func (rr *RoutingRule) BuildCondition() (Condition, error) {
    67  	conds := NewConditionChan()
    68  
    69  	if len(rr.Domain) > 0 {
    70  		switch rr.DomainMatcher {
    71  		case "linear":
    72  			matcher, err := NewDomainMatcher(rr.Domain)
    73  			if err != nil {
    74  				return nil, newError("failed to build domain condition").Base(err)
    75  			}
    76  			conds.Add(matcher)
    77  		case "mph", "hybrid":
    78  			fallthrough
    79  		default:
    80  			matcher, err := NewMphMatcherGroup(rr.Domain)
    81  			if err != nil {
    82  				return nil, newError("failed to build domain condition with MphDomainMatcher").Base(err)
    83  			}
    84  			newError("MphDomainMatcher is enabled for ", len(rr.Domain), " domain rule(s)").AtDebug().WriteToLog()
    85  			conds.Add(matcher)
    86  		}
    87  
    88  	}
    89  
    90  	if len(rr.UserEmail) > 0 {
    91  		conds.Add(NewUserMatcher(rr.UserEmail))
    92  	}
    93  
    94  	if len(rr.InboundTag) > 0 {
    95  		conds.Add(NewInboundTagMatcher(rr.InboundTag))
    96  	}
    97  
    98  	if rr.PortList != nil {
    99  		conds.Add(NewPortMatcher(rr.PortList, false))
   100  	} else if rr.PortRange != nil {
   101  		conds.Add(NewPortMatcher(&net.PortList{Range: []*net.PortRange{rr.PortRange}}, false))
   102  	}
   103  
   104  	if rr.SourcePortList != nil {
   105  		conds.Add(NewPortMatcher(rr.SourcePortList, true))
   106  	}
   107  
   108  	if len(rr.Networks) > 0 {
   109  		conds.Add(NewNetworkMatcher(rr.Networks))
   110  	} else if rr.NetworkList != nil {
   111  		conds.Add(NewNetworkMatcher(rr.NetworkList.Network))
   112  	}
   113  
   114  	if len(rr.Geoip) > 0 {
   115  		cond, err := NewMultiGeoIPMatcher(rr.Geoip, false)
   116  		if err != nil {
   117  			return nil, err
   118  		}
   119  		conds.Add(cond)
   120  	} else if len(rr.Cidr) > 0 {
   121  		cond, err := NewMultiGeoIPMatcher([]*GeoIP{{Cidr: rr.Cidr}}, false)
   122  		if err != nil {
   123  			return nil, err
   124  		}
   125  		conds.Add(cond)
   126  	}
   127  
   128  	if len(rr.SourceGeoip) > 0 {
   129  		cond, err := NewMultiGeoIPMatcher(rr.SourceGeoip, true)
   130  		if err != nil {
   131  			return nil, err
   132  		}
   133  		conds.Add(cond)
   134  	} else if len(rr.SourceCidr) > 0 {
   135  		cond, err := NewMultiGeoIPMatcher([]*GeoIP{{Cidr: rr.SourceCidr}}, true)
   136  		if err != nil {
   137  			return nil, err
   138  		}
   139  		conds.Add(cond)
   140  	}
   141  
   142  	if len(rr.Protocol) > 0 {
   143  		conds.Add(NewProtocolMatcher(rr.Protocol))
   144  	}
   145  
   146  	if len(rr.Attributes) > 0 {
   147  		cond, err := NewAttributeMatcher(rr.Attributes)
   148  		if err != nil {
   149  			return nil, err
   150  		}
   151  		conds.Add(cond)
   152  	}
   153  
   154  	if conds.Len() == 0 {
   155  		return nil, newError("this rule has no effective fields").AtWarning()
   156  	}
   157  
   158  	return conds, nil
   159  }
   160  
   161  func (br *BalancingRule) Build(ohm outbound.Manager) (*Balancer, error) {
   162  	return &Balancer{
   163  		selectors: br.OutboundSelector,
   164  		strategy:  &RandomStrategy{},
   165  		ohm:       ohm,
   166  	}, nil
   167  }