rule_default.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. package rule
  2. import (
  3. "context"
  4. "github.com/sagernet/sing-box/adapter"
  5. C "github.com/sagernet/sing-box/constant"
  6. "github.com/sagernet/sing-box/experimental/deprecated"
  7. "github.com/sagernet/sing-box/log"
  8. "github.com/sagernet/sing-box/option"
  9. "github.com/sagernet/sing/common"
  10. E "github.com/sagernet/sing/common/exceptions"
  11. "github.com/sagernet/sing/service"
  12. )
  13. func NewRule(ctx context.Context, logger log.ContextLogger, options option.Rule, checkOutbound bool) (adapter.Rule, error) {
  14. switch options.Type {
  15. case "", C.RuleTypeDefault:
  16. if !options.DefaultOptions.IsValid() {
  17. return nil, E.New("missing conditions")
  18. }
  19. switch options.DefaultOptions.Action {
  20. case "", C.RuleActionTypeRoute:
  21. if options.DefaultOptions.RouteOptions.Outbound == "" && checkOutbound {
  22. return nil, E.New("missing outbound field")
  23. }
  24. }
  25. return NewDefaultRule(ctx, logger, options.DefaultOptions)
  26. case C.RuleTypeLogical:
  27. if !options.LogicalOptions.IsValid() {
  28. return nil, E.New("missing conditions")
  29. }
  30. switch options.LogicalOptions.Action {
  31. case "", C.RuleActionTypeRoute:
  32. if options.LogicalOptions.RouteOptions.Outbound == "" && checkOutbound {
  33. return nil, E.New("missing outbound field")
  34. }
  35. }
  36. return NewLogicalRule(ctx, logger, options.LogicalOptions)
  37. default:
  38. return nil, E.New("unknown rule type: ", options.Type)
  39. }
  40. }
  41. var _ adapter.Rule = (*DefaultRule)(nil)
  42. type DefaultRule struct {
  43. abstractDefaultRule
  44. }
  45. type RuleItem interface {
  46. Match(metadata *adapter.InboundContext) bool
  47. String() string
  48. }
  49. func NewDefaultRule(ctx context.Context, logger log.ContextLogger, options option.DefaultRule) (*DefaultRule, error) {
  50. action, err := NewRuleAction(ctx, logger, options.RuleAction)
  51. if err != nil {
  52. return nil, E.Cause(err, "action")
  53. }
  54. rule := &DefaultRule{
  55. abstractDefaultRule{
  56. invert: options.Invert,
  57. action: action,
  58. },
  59. }
  60. router := service.FromContext[adapter.Router](ctx)
  61. networkManager := service.FromContext[adapter.NetworkManager](ctx)
  62. if len(options.Inbound) > 0 {
  63. item := NewInboundRule(options.Inbound)
  64. rule.items = append(rule.items, item)
  65. rule.allItems = append(rule.allItems, item)
  66. }
  67. if options.IPVersion > 0 {
  68. switch options.IPVersion {
  69. case 4, 6:
  70. item := NewIPVersionItem(options.IPVersion == 6)
  71. rule.items = append(rule.items, item)
  72. rule.allItems = append(rule.allItems, item)
  73. default:
  74. return nil, E.New("invalid ip version: ", options.IPVersion)
  75. }
  76. }
  77. if len(options.Network) > 0 {
  78. item := NewNetworkItem(options.Network)
  79. rule.items = append(rule.items, item)
  80. rule.allItems = append(rule.allItems, item)
  81. }
  82. if len(options.AuthUser) > 0 {
  83. item := NewAuthUserItem(options.AuthUser)
  84. rule.items = append(rule.items, item)
  85. rule.allItems = append(rule.allItems, item)
  86. }
  87. if len(options.Protocol) > 0 {
  88. item := NewProtocolItem(options.Protocol)
  89. rule.items = append(rule.items, item)
  90. rule.allItems = append(rule.allItems, item)
  91. }
  92. if len(options.Client) > 0 {
  93. item := NewClientItem(options.Client)
  94. rule.items = append(rule.items, item)
  95. rule.allItems = append(rule.allItems, item)
  96. }
  97. if len(options.Domain) > 0 || len(options.DomainSuffix) > 0 {
  98. item, err := NewDomainItem(options.Domain, options.DomainSuffix)
  99. if err != nil {
  100. return nil, err
  101. }
  102. rule.destinationAddressItems = append(rule.destinationAddressItems, item)
  103. rule.allItems = append(rule.allItems, item)
  104. }
  105. if len(options.DomainKeyword) > 0 {
  106. item := NewDomainKeywordItem(options.DomainKeyword)
  107. rule.destinationAddressItems = append(rule.destinationAddressItems, item)
  108. rule.allItems = append(rule.allItems, item)
  109. }
  110. if len(options.DomainRegex) > 0 {
  111. item, err := NewDomainRegexItem(options.DomainRegex)
  112. if err != nil {
  113. return nil, err
  114. }
  115. rule.destinationAddressItems = append(rule.destinationAddressItems, item)
  116. rule.allItems = append(rule.allItems, item)
  117. }
  118. if len(options.Geosite) > 0 {
  119. return nil, E.New("geosite database is deprecated in sing-box 1.8.0 and removed in sing-box 1.12.0")
  120. }
  121. if len(options.SourceGeoIP) > 0 {
  122. return nil, E.New("geoip database is deprecated in sing-box 1.8.0 and removed in sing-box 1.12.0")
  123. }
  124. if len(options.GeoIP) > 0 {
  125. return nil, E.New("geoip database is deprecated in sing-box 1.8.0 and removed in sing-box 1.12.0")
  126. }
  127. if len(options.SourceIPCIDR) > 0 {
  128. item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
  129. if err != nil {
  130. return nil, E.Cause(err, "source_ip_cidr")
  131. }
  132. rule.sourceAddressItems = append(rule.sourceAddressItems, item)
  133. rule.allItems = append(rule.allItems, item)
  134. }
  135. if options.SourceIPIsPrivate {
  136. item := NewIPIsPrivateItem(true)
  137. rule.sourceAddressItems = append(rule.sourceAddressItems, item)
  138. rule.allItems = append(rule.allItems, item)
  139. }
  140. if len(options.IPCIDR) > 0 {
  141. item, err := NewIPCIDRItem(false, options.IPCIDR)
  142. if err != nil {
  143. return nil, E.Cause(err, "ipcidr")
  144. }
  145. rule.destinationIPCIDRItems = append(rule.destinationIPCIDRItems, item)
  146. rule.allItems = append(rule.allItems, item)
  147. }
  148. if options.IPIsPrivate {
  149. item := NewIPIsPrivateItem(false)
  150. rule.destinationIPCIDRItems = append(rule.destinationIPCIDRItems, item)
  151. rule.allItems = append(rule.allItems, item)
  152. }
  153. if len(options.SourcePort) > 0 {
  154. item := NewPortItem(true, options.SourcePort)
  155. rule.sourcePortItems = append(rule.sourcePortItems, item)
  156. rule.allItems = append(rule.allItems, item)
  157. }
  158. if len(options.SourcePortRange) > 0 {
  159. item, err := NewPortRangeItem(true, options.SourcePortRange)
  160. if err != nil {
  161. return nil, E.Cause(err, "source_port_range")
  162. }
  163. rule.sourcePortItems = append(rule.sourcePortItems, item)
  164. rule.allItems = append(rule.allItems, item)
  165. }
  166. if len(options.Port) > 0 {
  167. item := NewPortItem(false, options.Port)
  168. rule.destinationPortItems = append(rule.destinationPortItems, item)
  169. rule.allItems = append(rule.allItems, item)
  170. }
  171. if len(options.PortRange) > 0 {
  172. item, err := NewPortRangeItem(false, options.PortRange)
  173. if err != nil {
  174. return nil, E.Cause(err, "port_range")
  175. }
  176. rule.destinationPortItems = append(rule.destinationPortItems, item)
  177. rule.allItems = append(rule.allItems, item)
  178. }
  179. if len(options.ProcessName) > 0 {
  180. item := NewProcessItem(options.ProcessName)
  181. rule.items = append(rule.items, item)
  182. rule.allItems = append(rule.allItems, item)
  183. }
  184. if len(options.ProcessPath) > 0 {
  185. item := NewProcessPathItem(options.ProcessPath)
  186. rule.items = append(rule.items, item)
  187. rule.allItems = append(rule.allItems, item)
  188. }
  189. if len(options.ProcessPathRegex) > 0 {
  190. item, err := NewProcessPathRegexItem(options.ProcessPathRegex)
  191. if err != nil {
  192. return nil, E.Cause(err, "process_path_regex")
  193. }
  194. rule.items = append(rule.items, item)
  195. rule.allItems = append(rule.allItems, item)
  196. }
  197. if len(options.PackageName) > 0 {
  198. item := NewPackageNameItem(options.PackageName)
  199. rule.items = append(rule.items, item)
  200. rule.allItems = append(rule.allItems, item)
  201. }
  202. if len(options.User) > 0 {
  203. item := NewUserItem(options.User)
  204. rule.items = append(rule.items, item)
  205. rule.allItems = append(rule.allItems, item)
  206. }
  207. if len(options.UserID) > 0 {
  208. item := NewUserIDItem(options.UserID)
  209. rule.items = append(rule.items, item)
  210. rule.allItems = append(rule.allItems, item)
  211. }
  212. if options.ClashMode != "" {
  213. item := NewClashModeItem(ctx, options.ClashMode)
  214. rule.items = append(rule.items, item)
  215. rule.allItems = append(rule.allItems, item)
  216. }
  217. if len(options.NetworkType) > 0 {
  218. item := NewNetworkTypeItem(networkManager, common.Map(options.NetworkType, option.InterfaceType.Build))
  219. rule.items = append(rule.items, item)
  220. rule.allItems = append(rule.allItems, item)
  221. }
  222. if options.NetworkIsExpensive {
  223. item := NewNetworkIsExpensiveItem(networkManager)
  224. rule.items = append(rule.items, item)
  225. rule.allItems = append(rule.allItems, item)
  226. }
  227. if options.NetworkIsConstrained {
  228. item := NewNetworkIsConstrainedItem(networkManager)
  229. rule.items = append(rule.items, item)
  230. rule.allItems = append(rule.allItems, item)
  231. }
  232. if len(options.WIFISSID) > 0 {
  233. item := NewWIFISSIDItem(networkManager, options.WIFISSID)
  234. rule.items = append(rule.items, item)
  235. rule.allItems = append(rule.allItems, item)
  236. }
  237. if len(options.WIFIBSSID) > 0 {
  238. item := NewWIFIBSSIDItem(networkManager, options.WIFIBSSID)
  239. rule.items = append(rule.items, item)
  240. rule.allItems = append(rule.allItems, item)
  241. }
  242. if options.InterfaceAddress != nil && options.InterfaceAddress.Size() > 0 {
  243. item := NewInterfaceAddressItem(networkManager, options.InterfaceAddress)
  244. rule.items = append(rule.items, item)
  245. rule.allItems = append(rule.allItems, item)
  246. }
  247. if options.NetworkInterfaceAddress != nil && options.NetworkInterfaceAddress.Size() > 0 {
  248. item := NewNetworkInterfaceAddressItem(networkManager, options.NetworkInterfaceAddress)
  249. rule.items = append(rule.items, item)
  250. rule.allItems = append(rule.allItems, item)
  251. }
  252. if len(options.DefaultInterfaceAddress) > 0 {
  253. item := NewDefaultInterfaceAddressItem(networkManager, options.DefaultInterfaceAddress)
  254. rule.items = append(rule.items, item)
  255. rule.allItems = append(rule.allItems, item)
  256. }
  257. if len(options.PreferredBy) > 0 {
  258. item := NewPreferredByItem(ctx, options.PreferredBy)
  259. rule.items = append(rule.items, item)
  260. rule.allItems = append(rule.allItems, item)
  261. }
  262. if len(options.RuleSet) > 0 {
  263. var matchSource bool
  264. if options.RuleSetIPCIDRMatchSource {
  265. matchSource = true
  266. } else
  267. //nolint:staticcheck
  268. if options.Deprecated_RulesetIPCIDRMatchSource {
  269. matchSource = true
  270. deprecated.Report(ctx, deprecated.OptionBadMatchSource)
  271. }
  272. item := NewRuleSetItem(router, options.RuleSet, matchSource, false)
  273. rule.items = append(rule.items, item)
  274. rule.allItems = append(rule.allItems, item)
  275. }
  276. return rule, nil
  277. }
  278. var _ adapter.Rule = (*LogicalRule)(nil)
  279. type LogicalRule struct {
  280. abstractLogicalRule
  281. }
  282. func NewLogicalRule(ctx context.Context, logger log.ContextLogger, options option.LogicalRule) (*LogicalRule, error) {
  283. action, err := NewRuleAction(ctx, logger, options.RuleAction)
  284. if err != nil {
  285. return nil, E.Cause(err, "action")
  286. }
  287. rule := &LogicalRule{
  288. abstractLogicalRule{
  289. rules: make([]adapter.HeadlessRule, len(options.Rules)),
  290. invert: options.Invert,
  291. action: action,
  292. },
  293. }
  294. switch options.Mode {
  295. case C.LogicalTypeAnd:
  296. rule.mode = C.LogicalTypeAnd
  297. case C.LogicalTypeOr:
  298. rule.mode = C.LogicalTypeOr
  299. default:
  300. return nil, E.New("unknown logical mode: ", options.Mode)
  301. }
  302. for i, subOptions := range options.Rules {
  303. subRule, err := NewRule(ctx, logger, subOptions, false)
  304. if err != nil {
  305. return nil, E.Cause(err, "sub rule[", i, "]")
  306. }
  307. rule.rules[i] = subRule
  308. }
  309. return rule, nil
  310. }