github.com/sagernet/sing-box@v1.9.0-rc.20/route/rule_default.go (about)

     1  package route
     2  
     3  import (
     4  	"github.com/sagernet/sing-box/adapter"
     5  	C "github.com/sagernet/sing-box/constant"
     6  	"github.com/sagernet/sing-box/log"
     7  	"github.com/sagernet/sing-box/option"
     8  	E "github.com/sagernet/sing/common/exceptions"
     9  )
    10  
    11  func NewRule(router adapter.Router, logger log.ContextLogger, options option.Rule, checkOutbound bool) (adapter.Rule, error) {
    12  	switch options.Type {
    13  	case "", C.RuleTypeDefault:
    14  		if !options.DefaultOptions.IsValid() {
    15  			return nil, E.New("missing conditions")
    16  		}
    17  		if options.DefaultOptions.Outbound == "" && checkOutbound {
    18  			return nil, E.New("missing outbound field")
    19  		}
    20  		return NewDefaultRule(router, logger, options.DefaultOptions)
    21  	case C.RuleTypeLogical:
    22  		if !options.LogicalOptions.IsValid() {
    23  			return nil, E.New("missing conditions")
    24  		}
    25  		if options.LogicalOptions.Outbound == "" && checkOutbound {
    26  			return nil, E.New("missing outbound field")
    27  		}
    28  		return NewLogicalRule(router, logger, options.LogicalOptions)
    29  	default:
    30  		return nil, E.New("unknown rule type: ", options.Type)
    31  	}
    32  }
    33  
    34  var _ adapter.Rule = (*DefaultRule)(nil)
    35  
    36  type DefaultRule struct {
    37  	abstractDefaultRule
    38  }
    39  
    40  type RuleItem interface {
    41  	Match(metadata *adapter.InboundContext) bool
    42  	String() string
    43  }
    44  
    45  func NewDefaultRule(router adapter.Router, logger log.ContextLogger, options option.DefaultRule) (*DefaultRule, error) {
    46  	rule := &DefaultRule{
    47  		abstractDefaultRule{
    48  			invert:   options.Invert,
    49  			outbound: options.Outbound,
    50  		},
    51  	}
    52  	if len(options.Inbound) > 0 {
    53  		item := NewInboundRule(options.Inbound)
    54  		rule.items = append(rule.items, item)
    55  		rule.allItems = append(rule.allItems, item)
    56  	}
    57  	if options.IPVersion > 0 {
    58  		switch options.IPVersion {
    59  		case 4, 6:
    60  			item := NewIPVersionItem(options.IPVersion == 6)
    61  			rule.items = append(rule.items, item)
    62  			rule.allItems = append(rule.allItems, item)
    63  		default:
    64  			return nil, E.New("invalid ip version: ", options.IPVersion)
    65  		}
    66  	}
    67  	if len(options.Network) > 0 {
    68  		item := NewNetworkItem(options.Network)
    69  		rule.items = append(rule.items, item)
    70  		rule.allItems = append(rule.allItems, item)
    71  	}
    72  	if len(options.AuthUser) > 0 {
    73  		item := NewAuthUserItem(options.AuthUser)
    74  		rule.items = append(rule.items, item)
    75  		rule.allItems = append(rule.allItems, item)
    76  	}
    77  	if len(options.Protocol) > 0 {
    78  		item := NewProtocolItem(options.Protocol)
    79  		rule.items = append(rule.items, item)
    80  		rule.allItems = append(rule.allItems, item)
    81  	}
    82  	if len(options.Domain) > 0 || len(options.DomainSuffix) > 0 {
    83  		item := NewDomainItem(options.Domain, options.DomainSuffix)
    84  		rule.destinationAddressItems = append(rule.destinationAddressItems, item)
    85  		rule.allItems = append(rule.allItems, item)
    86  	}
    87  	if len(options.DomainKeyword) > 0 {
    88  		item := NewDomainKeywordItem(options.DomainKeyword)
    89  		rule.destinationAddressItems = append(rule.destinationAddressItems, item)
    90  		rule.allItems = append(rule.allItems, item)
    91  	}
    92  	if len(options.DomainRegex) > 0 {
    93  		item, err := NewDomainRegexItem(options.DomainRegex)
    94  		if err != nil {
    95  			return nil, E.Cause(err, "domain_regex")
    96  		}
    97  		rule.destinationAddressItems = append(rule.destinationAddressItems, item)
    98  		rule.allItems = append(rule.allItems, item)
    99  	}
   100  	if len(options.Geosite) > 0 {
   101  		item := NewGeositeItem(router, logger, options.Geosite)
   102  		rule.destinationAddressItems = append(rule.destinationAddressItems, item)
   103  		rule.allItems = append(rule.allItems, item)
   104  	}
   105  	if len(options.SourceGeoIP) > 0 {
   106  		item := NewGeoIPItem(router, logger, true, options.SourceGeoIP)
   107  		rule.sourceAddressItems = append(rule.sourceAddressItems, item)
   108  		rule.allItems = append(rule.allItems, item)
   109  	}
   110  	if len(options.GeoIP) > 0 {
   111  		item := NewGeoIPItem(router, logger, false, options.GeoIP)
   112  		rule.destinationIPCIDRItems = append(rule.destinationIPCIDRItems, item)
   113  		rule.allItems = append(rule.allItems, item)
   114  	}
   115  	if len(options.SourceIPCIDR) > 0 {
   116  		item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
   117  		if err != nil {
   118  			return nil, E.Cause(err, "source_ip_cidr")
   119  		}
   120  		rule.sourceAddressItems = append(rule.sourceAddressItems, item)
   121  		rule.allItems = append(rule.allItems, item)
   122  	}
   123  	if options.SourceIPIsPrivate {
   124  		item := NewIPIsPrivateItem(true)
   125  		rule.sourceAddressItems = append(rule.sourceAddressItems, item)
   126  		rule.allItems = append(rule.allItems, item)
   127  	}
   128  	if len(options.IPCIDR) > 0 {
   129  		item, err := NewIPCIDRItem(false, options.IPCIDR)
   130  		if err != nil {
   131  			return nil, E.Cause(err, "ipcidr")
   132  		}
   133  		rule.destinationIPCIDRItems = append(rule.destinationIPCIDRItems, item)
   134  		rule.allItems = append(rule.allItems, item)
   135  	}
   136  	if options.IPIsPrivate {
   137  		item := NewIPIsPrivateItem(false)
   138  		rule.destinationIPCIDRItems = append(rule.destinationIPCIDRItems, item)
   139  		rule.allItems = append(rule.allItems, item)
   140  	}
   141  	if len(options.SourcePort) > 0 {
   142  		item := NewPortItem(true, options.SourcePort)
   143  		rule.sourcePortItems = append(rule.sourcePortItems, item)
   144  		rule.allItems = append(rule.allItems, item)
   145  	}
   146  	if len(options.SourcePortRange) > 0 {
   147  		item, err := NewPortRangeItem(true, options.SourcePortRange)
   148  		if err != nil {
   149  			return nil, E.Cause(err, "source_port_range")
   150  		}
   151  		rule.sourcePortItems = append(rule.sourcePortItems, item)
   152  		rule.allItems = append(rule.allItems, item)
   153  	}
   154  	if len(options.Port) > 0 {
   155  		item := NewPortItem(false, options.Port)
   156  		rule.destinationPortItems = append(rule.destinationPortItems, item)
   157  		rule.allItems = append(rule.allItems, item)
   158  	}
   159  	if len(options.PortRange) > 0 {
   160  		item, err := NewPortRangeItem(false, options.PortRange)
   161  		if err != nil {
   162  			return nil, E.Cause(err, "port_range")
   163  		}
   164  		rule.destinationPortItems = append(rule.destinationPortItems, item)
   165  		rule.allItems = append(rule.allItems, item)
   166  	}
   167  	if len(options.ProcessName) > 0 {
   168  		item := NewProcessItem(options.ProcessName)
   169  		rule.items = append(rule.items, item)
   170  		rule.allItems = append(rule.allItems, item)
   171  	}
   172  	if len(options.ProcessPath) > 0 {
   173  		item := NewProcessPathItem(options.ProcessPath)
   174  		rule.items = append(rule.items, item)
   175  		rule.allItems = append(rule.allItems, item)
   176  	}
   177  	if len(options.PackageName) > 0 {
   178  		item := NewPackageNameItem(options.PackageName)
   179  		rule.items = append(rule.items, item)
   180  		rule.allItems = append(rule.allItems, item)
   181  	}
   182  	if len(options.User) > 0 {
   183  		item := NewUserItem(options.User)
   184  		rule.items = append(rule.items, item)
   185  		rule.allItems = append(rule.allItems, item)
   186  	}
   187  	if len(options.UserID) > 0 {
   188  		item := NewUserIDItem(options.UserID)
   189  		rule.items = append(rule.items, item)
   190  		rule.allItems = append(rule.allItems, item)
   191  	}
   192  	if options.ClashMode != "" {
   193  		item := NewClashModeItem(router, options.ClashMode)
   194  		rule.items = append(rule.items, item)
   195  		rule.allItems = append(rule.allItems, item)
   196  	}
   197  	if len(options.WIFISSID) > 0 {
   198  		item := NewWIFISSIDItem(router, options.WIFISSID)
   199  		rule.items = append(rule.items, item)
   200  		rule.allItems = append(rule.allItems, item)
   201  	}
   202  	if len(options.WIFIBSSID) > 0 {
   203  		item := NewWIFIBSSIDItem(router, options.WIFIBSSID)
   204  		rule.items = append(rule.items, item)
   205  		rule.allItems = append(rule.allItems, item)
   206  	}
   207  	if len(options.RuleSet) > 0 {
   208  		item := NewRuleSetItem(router, options.RuleSet, options.RuleSetIPCIDRMatchSource)
   209  		rule.items = append(rule.items, item)
   210  		rule.allItems = append(rule.allItems, item)
   211  	}
   212  	return rule, nil
   213  }
   214  
   215  var _ adapter.Rule = (*LogicalRule)(nil)
   216  
   217  type LogicalRule struct {
   218  	abstractLogicalRule
   219  }
   220  
   221  func NewLogicalRule(router adapter.Router, logger log.ContextLogger, options option.LogicalRule) (*LogicalRule, error) {
   222  	r := &LogicalRule{
   223  		abstractLogicalRule{
   224  			rules:    make([]adapter.HeadlessRule, len(options.Rules)),
   225  			invert:   options.Invert,
   226  			outbound: options.Outbound,
   227  		},
   228  	}
   229  	switch options.Mode {
   230  	case C.LogicalTypeAnd:
   231  		r.mode = C.LogicalTypeAnd
   232  	case C.LogicalTypeOr:
   233  		r.mode = C.LogicalTypeOr
   234  	default:
   235  		return nil, E.New("unknown logical mode: ", options.Mode)
   236  	}
   237  	for i, subRule := range options.Rules {
   238  		rule, err := NewRule(router, logger, subRule, false)
   239  		if err != nil {
   240  			return nil, E.Cause(err, "sub rule[", i, "]")
   241  		}
   242  		r.rules[i] = rule
   243  	}
   244  	return r, nil
   245  }