github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/route/rule_default.go (about)

     1  package route
     2  
     3  import (
     4  	"github.com/inazumav/sing-box/adapter"
     5  	C "github.com/inazumav/sing-box/constant"
     6  	"github.com/inazumav/sing-box/log"
     7  	"github.com/inazumav/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) (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 == "" {
    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 == "" {
    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.destinationAddressItems = append(rule.destinationAddressItems, 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_ipcidr")
   119  		}
   120  		rule.sourceAddressItems = append(rule.sourceAddressItems, item)
   121  		rule.allItems = append(rule.allItems, item)
   122  	}
   123  	if len(options.IPCIDR) > 0 {
   124  		item, err := NewIPCIDRItem(false, options.IPCIDR)
   125  		if err != nil {
   126  			return nil, E.Cause(err, "ipcidr")
   127  		}
   128  		rule.destinationAddressItems = append(rule.destinationAddressItems, item)
   129  		rule.allItems = append(rule.allItems, item)
   130  	}
   131  	if len(options.SourcePort) > 0 {
   132  		item := NewPortItem(true, options.SourcePort)
   133  		rule.sourcePortItems = append(rule.sourcePortItems, item)
   134  		rule.allItems = append(rule.allItems, item)
   135  	}
   136  	if len(options.SourcePortRange) > 0 {
   137  		item, err := NewPortRangeItem(true, options.SourcePortRange)
   138  		if err != nil {
   139  			return nil, E.Cause(err, "source_port_range")
   140  		}
   141  		rule.sourcePortItems = append(rule.sourcePortItems, item)
   142  		rule.allItems = append(rule.allItems, item)
   143  	}
   144  	if len(options.Port) > 0 {
   145  		item := NewPortItem(false, options.Port)
   146  		rule.destinationPortItems = append(rule.destinationPortItems, item)
   147  		rule.allItems = append(rule.allItems, item)
   148  	}
   149  	if len(options.PortRange) > 0 {
   150  		item, err := NewPortRangeItem(false, options.PortRange)
   151  		if err != nil {
   152  			return nil, E.Cause(err, "port_range")
   153  		}
   154  		rule.destinationPortItems = append(rule.destinationPortItems, item)
   155  		rule.allItems = append(rule.allItems, item)
   156  	}
   157  	if len(options.ProcessName) > 0 {
   158  		item := NewProcessItem(options.ProcessName)
   159  		rule.items = append(rule.items, item)
   160  		rule.allItems = append(rule.allItems, item)
   161  	}
   162  	if len(options.ProcessPath) > 0 {
   163  		item := NewProcessPathItem(options.ProcessPath)
   164  		rule.items = append(rule.items, item)
   165  		rule.allItems = append(rule.allItems, item)
   166  	}
   167  	if len(options.PackageName) > 0 {
   168  		item := NewPackageNameItem(options.PackageName)
   169  		rule.items = append(rule.items, item)
   170  		rule.allItems = append(rule.allItems, item)
   171  	}
   172  	if len(options.User) > 0 {
   173  		item := NewUserItem(options.User)
   174  		rule.items = append(rule.items, item)
   175  		rule.allItems = append(rule.allItems, item)
   176  	}
   177  	if len(options.UserID) > 0 {
   178  		item := NewUserIDItem(options.UserID)
   179  		rule.items = append(rule.items, item)
   180  		rule.allItems = append(rule.allItems, item)
   181  	}
   182  	if options.ClashMode != "" {
   183  		item := NewClashModeItem(router, options.ClashMode)
   184  		rule.items = append(rule.items, item)
   185  		rule.allItems = append(rule.allItems, item)
   186  	}
   187  	return rule, nil
   188  }
   189  
   190  var _ adapter.Rule = (*LogicalRule)(nil)
   191  
   192  type LogicalRule struct {
   193  	abstractLogicalRule
   194  }
   195  
   196  func NewLogicalRule(router adapter.Router, logger log.ContextLogger, options option.LogicalRule) (*LogicalRule, error) {
   197  	r := &LogicalRule{
   198  		abstractLogicalRule{
   199  			rules:    make([]adapter.Rule, len(options.Rules)),
   200  			invert:   options.Invert,
   201  			outbound: options.Outbound,
   202  		},
   203  	}
   204  	switch options.Mode {
   205  	case C.LogicalTypeAnd:
   206  		r.mode = C.LogicalTypeAnd
   207  	case C.LogicalTypeOr:
   208  		r.mode = C.LogicalTypeOr
   209  	default:
   210  		return nil, E.New("unknown logical mode: ", options.Mode)
   211  	}
   212  	for i, subRule := range options.Rules {
   213  		rule, err := NewDefaultRule(router, logger, subRule)
   214  		if err != nil {
   215  			return nil, E.Cause(err, "sub rule[", i, "]")
   216  		}
   217  		r.rules[i] = rule
   218  	}
   219  	return r, nil
   220  }