Files
Xray-core/app/router/config.go
T

166 lines
3.9 KiB
Go
Raw Normal View History

2020-11-25 19:01:53 +08:00
package router
import (
2024-06-29 14:32:57 -04:00
"context"
2023-06-27 04:04:09 -04:00
"regexp"
2023-05-21 11:26:22 -04:00
"strings"
2024-06-29 14:32:57 -04:00
"github.com/xtls/xray-core/common/errors"
2020-12-04 09:36:16 +08:00
"github.com/xtls/xray-core/features/outbound"
"github.com/xtls/xray-core/features/routing"
2020-11-25 19:01:53 +08:00
)
type Rule struct {
Tag string
2024-03-29 19:17:36 +04:00
RuleTag string
2020-11-25 19:01:53 +08:00
Balancer *Balancer
Condition Condition
2026-03-07 13:49:46 +03:00
Webhook *WebhookNotifier
2020-11-25 19:01:53 +08:00
}
func (r *Rule) GetTag() (string, error) {
if r.Balancer != nil {
return r.Balancer.PickOutbound()
}
return r.Tag, nil
}
// Apply checks rule matching of current routing context.
func (r *Rule) Apply(ctx routing.Context) bool {
return r.Condition.Apply(ctx)
}
func (rr *RoutingRule) BuildCondition() (Condition, error) {
conds := NewConditionChan()
if len(rr.InboundTag) > 0 {
conds.Add(NewInboundTagMatcher(rr.InboundTag))
2020-11-25 19:01:53 +08:00
}
if len(rr.Networks) > 0 {
conds.Add(NewNetworkMatcher(rr.Networks))
}
if len(rr.Protocol) > 0 {
conds.Add(NewProtocolMatcher(rr.Protocol))
2020-11-25 19:01:53 +08:00
}
if rr.PortList != nil {
conds.Add(NewPortMatcher(rr.PortList, MatcherAsType_Target))
2020-11-25 19:01:53 +08:00
}
if rr.SourcePortList != nil {
conds.Add(NewPortMatcher(rr.SourcePortList, MatcherAsType_Source))
}
if rr.LocalPortList != nil {
conds.Add(NewPortMatcher(rr.LocalPortList, MatcherAsType_Local))
2020-11-25 19:01:53 +08:00
}
if rr.VlessRouteList != nil {
conds.Add(NewPortMatcher(rr.VlessRouteList, MatcherAsType_VlessRoute))
}
if len(rr.UserEmail) > 0 {
conds.Add(NewUserMatcher(rr.UserEmail))
}
if len(rr.Attributes) > 0 {
configuredKeys := make(map[string]*regexp.Regexp)
for key, value := range rr.Attributes {
configuredKeys[strings.ToLower(key)] = regexp.MustCompile(value)
}
conds.Add(&AttributeMatcher{configuredKeys})
2020-11-25 19:01:53 +08:00
}
2026-04-14 00:42:29 +08:00
if len(rr.Ip) > 0 {
cond, err := NewIPMatcher(rr.Ip, MatcherAsType_Target)
2020-11-25 19:01:53 +08:00
if err != nil {
return nil, err
}
conds.Add(cond)
}
2026-04-14 00:42:29 +08:00
if len(rr.SourceIp) > 0 {
cond, err := NewIPMatcher(rr.SourceIp, MatcherAsType_Source)
if err != nil {
return nil, err
}
conds.Add(cond)
}
2026-04-14 00:42:29 +08:00
if len(rr.LocalIp) > 0 {
cond, err := NewIPMatcher(rr.LocalIp, MatcherAsType_Local)
2020-11-25 19:01:53 +08:00
if err != nil {
return nil, err
}
conds.Add(cond)
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")
2020-11-25 19:01:53 +08:00
}
if len(rr.Domain) > 0 {
2026-04-14 00:42:29 +08:00
cond, err := NewDomainMatcher(rr.Domain)
if err != nil {
return nil, err
2020-11-25 19:01:53 +08:00
}
2026-04-14 00:42:29 +08:00
conds.Add(cond)
2020-11-25 19:01:53 +08:00
}
if len(rr.Process) > 0 {
conds.Add(NewProcessNameMatcher(rr.Process))
2026-01-05 09:12:13 +08:00
}
2020-11-25 19:01:53 +08:00
if conds.Len() == 0 {
2024-06-29 14:32:57 -04:00
return nil, errors.New("this rule has no effective fields").AtWarning()
2020-11-25 19:01:53 +08:00
}
return conds, nil
}
2024-02-17 22:51:37 -05:00
// Build builds the balancing rule
func (br *BalancingRule) Build(ohm outbound.Manager, dispatcher routing.Dispatcher) (*Balancer, error) {
switch strings.ToLower(br.Strategy) {
case "leastping":
2021-10-26 01:00:31 -04:00
return &Balancer{
selectors: br.OutboundSelector,
strategy: &LeastPingStrategy{},
fallbackTag: br.FallbackTag,
ohm: ohm,
2021-10-26 01:00:31 -04:00
}, nil
2024-02-17 22:51:37 -05:00
case "roundrobin":
return &Balancer{
selectors: br.OutboundSelector,
strategy: &RoundRobinStrategy{FallbackTag: br.FallbackTag},
fallbackTag: br.FallbackTag,
ohm: ohm,
}, nil
2024-02-17 22:51:37 -05:00
case "leastload":
i, err := br.StrategySettings.GetInstance()
if err != nil {
return nil, err
}
s, ok := i.(*StrategyLeastLoadConfig)
if !ok {
2024-06-29 14:32:57 -04:00
return nil, errors.New("not a StrategyLeastLoadConfig").AtError()
2024-02-17 22:51:37 -05:00
}
leastLoadStrategy := NewLeastLoadStrategy(s)
return &Balancer{
selectors: br.OutboundSelector,
2024-03-29 19:17:36 +04:00
ohm: ohm,
fallbackTag: br.FallbackTag,
strategy: leastLoadStrategy,
2024-02-17 22:51:37 -05:00
}, nil
2021-10-26 01:00:31 -04:00
case "random":
fallthrough
2024-02-17 22:51:37 -05:00
case "":
2021-10-26 01:00:31 -04:00
return &Balancer{
selectors: br.OutboundSelector,
2024-03-29 19:17:36 +04:00
ohm: ohm,
fallbackTag: br.FallbackTag,
strategy: &RandomStrategy{FallbackTag: br.FallbackTag},
2021-10-26 01:00:31 -04:00
}, nil
2024-02-17 22:51:37 -05:00
default:
2024-06-29 14:32:57 -04:00
return nil, errors.New("unrecognized balancer type")
2021-10-26 01:00:31 -04:00
}
2020-11-25 19:01:53 +08:00
}