rule.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. package route
  2. import (
  3. "strings"
  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. "github.com/sagernet/sing/common"
  9. E "github.com/sagernet/sing/common/exceptions"
  10. F "github.com/sagernet/sing/common/format"
  11. )
  12. func NewRule(router adapter.Router, logger log.ContextLogger, options option.Rule) (adapter.Rule, error) {
  13. if common.IsEmptyByEquals(options) {
  14. return nil, E.New("empty rule config")
  15. }
  16. switch options.Type {
  17. case "", C.RuleTypeDefault:
  18. if !options.DefaultOptions.IsValid() {
  19. return nil, E.New("missing conditions")
  20. }
  21. if options.DefaultOptions.Outbound == "" {
  22. return nil, E.New("missing outbound field")
  23. }
  24. return NewDefaultRule(router, logger, options.DefaultOptions)
  25. case C.RuleTypeLogical:
  26. if !options.LogicalOptions.IsValid() {
  27. return nil, E.New("missing conditions")
  28. }
  29. if options.LogicalOptions.Outbound == "" {
  30. return nil, E.New("missing outbound field")
  31. }
  32. return NewLogicalRule(router, logger, options.LogicalOptions)
  33. default:
  34. return nil, E.New("unknown rule type: ", options.Type)
  35. }
  36. }
  37. var _ adapter.Rule = (*DefaultRule)(nil)
  38. type DefaultRule struct {
  39. items []RuleItem
  40. sourceAddressItems []RuleItem
  41. destinationAddressItems []RuleItem
  42. allItems []RuleItem
  43. invert bool
  44. outbound string
  45. }
  46. type RuleItem interface {
  47. Match(metadata *adapter.InboundContext) bool
  48. String() string
  49. }
  50. func NewDefaultRule(router adapter.Router, logger log.ContextLogger, options option.DefaultRule) (*DefaultRule, error) {
  51. rule := &DefaultRule{
  52. invert: options.Invert,
  53. outbound: options.Outbound,
  54. }
  55. if len(options.Inbound) > 0 {
  56. item := NewInboundRule(options.Inbound)
  57. rule.items = append(rule.items, item)
  58. rule.allItems = append(rule.allItems, item)
  59. }
  60. if options.IPVersion > 0 {
  61. switch options.IPVersion {
  62. case 4, 6:
  63. item := NewIPVersionItem(options.IPVersion == 6)
  64. rule.items = append(rule.items, item)
  65. rule.allItems = append(rule.allItems, item)
  66. default:
  67. return nil, E.New("invalid ip version: ", options.IPVersion)
  68. }
  69. }
  70. if options.Network != "" {
  71. switch options.Network {
  72. case C.NetworkTCP, C.NetworkUDP:
  73. item := NewNetworkItem(options.Network)
  74. rule.items = append(rule.items, item)
  75. rule.allItems = append(rule.allItems, item)
  76. default:
  77. return nil, E.New("invalid network: ", options.Network)
  78. }
  79. }
  80. if len(options.AuthUser) > 0 {
  81. item := NewAuthUserItem(options.AuthUser)
  82. rule.items = append(rule.items, item)
  83. rule.allItems = append(rule.allItems, item)
  84. }
  85. if len(options.Protocol) > 0 {
  86. item := NewProtocolItem(options.Protocol)
  87. rule.items = append(rule.items, item)
  88. rule.allItems = append(rule.allItems, item)
  89. }
  90. if len(options.Domain) > 0 || len(options.DomainSuffix) > 0 {
  91. item := NewDomainItem(options.Domain, options.DomainSuffix)
  92. rule.destinationAddressItems = append(rule.destinationAddressItems, item)
  93. rule.allItems = append(rule.allItems, item)
  94. }
  95. if len(options.DomainKeyword) > 0 {
  96. item := NewDomainKeywordItem(options.DomainKeyword)
  97. rule.destinationAddressItems = append(rule.destinationAddressItems, item)
  98. rule.allItems = append(rule.allItems, item)
  99. }
  100. if len(options.DomainRegex) > 0 {
  101. item, err := NewDomainRegexItem(options.DomainRegex)
  102. if err != nil {
  103. return nil, E.Cause(err, "domain_regex")
  104. }
  105. rule.destinationAddressItems = append(rule.destinationAddressItems, item)
  106. rule.allItems = append(rule.allItems, item)
  107. }
  108. if len(options.Geosite) > 0 {
  109. item := NewGeositeItem(router, logger, options.Geosite)
  110. rule.destinationAddressItems = append(rule.destinationAddressItems, item)
  111. rule.allItems = append(rule.allItems, item)
  112. }
  113. if len(options.SourceGeoIP) > 0 {
  114. item := NewGeoIPItem(router, logger, true, options.SourceGeoIP)
  115. rule.sourceAddressItems = append(rule.sourceAddressItems, item)
  116. rule.allItems = append(rule.allItems, item)
  117. }
  118. if len(options.GeoIP) > 0 {
  119. item := NewGeoIPItem(router, logger, false, options.GeoIP)
  120. rule.destinationAddressItems = append(rule.destinationAddressItems, item)
  121. rule.allItems = append(rule.allItems, item)
  122. }
  123. if len(options.SourceIPCIDR) > 0 {
  124. item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
  125. if err != nil {
  126. return nil, E.Cause(err, "source_ipcidr")
  127. }
  128. rule.sourceAddressItems = append(rule.sourceAddressItems, item)
  129. rule.allItems = append(rule.allItems, item)
  130. }
  131. if len(options.IPCIDR) > 0 {
  132. item, err := NewIPCIDRItem(false, options.IPCIDR)
  133. if err != nil {
  134. return nil, E.Cause(err, "ipcidr")
  135. }
  136. rule.destinationAddressItems = append(rule.destinationAddressItems, item)
  137. rule.allItems = append(rule.allItems, item)
  138. }
  139. if len(options.SourcePort) > 0 {
  140. item := NewPortItem(true, options.SourcePort)
  141. rule.items = append(rule.items, item)
  142. rule.allItems = append(rule.allItems, item)
  143. }
  144. if len(options.Port) > 0 {
  145. item := NewPortItem(false, options.Port)
  146. rule.items = append(rule.items, item)
  147. rule.allItems = append(rule.allItems, item)
  148. }
  149. if len(options.ProcessName) > 0 {
  150. item := NewProcessItem(options.ProcessName)
  151. rule.items = append(rule.items, item)
  152. rule.allItems = append(rule.allItems, item)
  153. }
  154. if len(options.PackageName) > 0 {
  155. item := NewPackageNameItem(options.PackageName)
  156. rule.items = append(rule.items, item)
  157. rule.allItems = append(rule.allItems, item)
  158. }
  159. if len(options.User) > 0 {
  160. item := NewUserItem(options.User)
  161. rule.items = append(rule.items, item)
  162. rule.allItems = append(rule.allItems, item)
  163. }
  164. if len(options.UserID) > 0 {
  165. item := NewUserIDItem(options.UserID)
  166. rule.items = append(rule.items, item)
  167. rule.allItems = append(rule.allItems, item)
  168. }
  169. return rule, nil
  170. }
  171. func (r *DefaultRule) Type() string {
  172. return C.RuleTypeDefault
  173. }
  174. func (r *DefaultRule) Start() error {
  175. for _, item := range r.allItems {
  176. err := common.Start(item)
  177. if err != nil {
  178. return err
  179. }
  180. }
  181. return nil
  182. }
  183. func (r *DefaultRule) Close() error {
  184. for _, item := range r.allItems {
  185. err := common.Close(item)
  186. if err != nil {
  187. return err
  188. }
  189. }
  190. return nil
  191. }
  192. func (r *DefaultRule) UpdateGeosite() error {
  193. for _, item := range r.allItems {
  194. if geositeItem, isSite := item.(*GeositeItem); isSite {
  195. err := geositeItem.Update()
  196. if err != nil {
  197. return err
  198. }
  199. }
  200. }
  201. return nil
  202. }
  203. func (r *DefaultRule) Match(metadata *adapter.InboundContext) bool {
  204. for _, item := range r.items {
  205. if !item.Match(metadata) {
  206. return r.invert
  207. }
  208. }
  209. if len(r.sourceAddressItems) > 0 {
  210. var sourceAddressMatch bool
  211. for _, item := range r.sourceAddressItems {
  212. if item.Match(metadata) {
  213. sourceAddressMatch = true
  214. break
  215. }
  216. }
  217. if !sourceAddressMatch {
  218. return r.invert
  219. }
  220. }
  221. if len(r.destinationAddressItems) > 0 {
  222. var destinationAddressMatch bool
  223. for _, item := range r.destinationAddressItems {
  224. if item.Match(metadata) {
  225. destinationAddressMatch = true
  226. break
  227. }
  228. }
  229. if !destinationAddressMatch {
  230. return r.invert
  231. }
  232. }
  233. return !r.invert
  234. }
  235. func (r *DefaultRule) Outbound() string {
  236. return r.outbound
  237. }
  238. func (r *DefaultRule) String() string {
  239. return strings.Join(F.MapToString(r.allItems), " ")
  240. }
  241. var _ adapter.Rule = (*LogicalRule)(nil)
  242. type LogicalRule struct {
  243. mode string
  244. rules []*DefaultRule
  245. invert bool
  246. outbound string
  247. }
  248. func NewLogicalRule(router adapter.Router, logger log.ContextLogger, options option.LogicalRule) (*LogicalRule, error) {
  249. r := &LogicalRule{
  250. rules: make([]*DefaultRule, len(options.Rules)),
  251. invert: options.Invert,
  252. outbound: options.Outbound,
  253. }
  254. switch options.Mode {
  255. case C.LogicalTypeAnd:
  256. r.mode = C.LogicalTypeAnd
  257. case C.LogicalTypeOr:
  258. r.mode = C.LogicalTypeOr
  259. default:
  260. return nil, E.New("unknown logical mode: ", options.Mode)
  261. }
  262. for i, subRule := range options.Rules {
  263. rule, err := NewDefaultRule(router, logger, subRule)
  264. if err != nil {
  265. return nil, E.Cause(err, "sub rule[", i, "]")
  266. }
  267. r.rules[i] = rule
  268. }
  269. return r, nil
  270. }
  271. func (r *LogicalRule) Type() string {
  272. return C.RuleTypeLogical
  273. }
  274. func (r *LogicalRule) UpdateGeosite() error {
  275. for _, rule := range r.rules {
  276. err := rule.UpdateGeosite()
  277. if err != nil {
  278. return err
  279. }
  280. }
  281. return nil
  282. }
  283. func (r *LogicalRule) Start() error {
  284. for _, rule := range r.rules {
  285. err := rule.Start()
  286. if err != nil {
  287. return err
  288. }
  289. }
  290. return nil
  291. }
  292. func (r *LogicalRule) Close() error {
  293. for _, rule := range r.rules {
  294. err := rule.Close()
  295. if err != nil {
  296. return err
  297. }
  298. }
  299. return nil
  300. }
  301. func (r *LogicalRule) Match(metadata *adapter.InboundContext) bool {
  302. if r.mode == C.LogicalTypeAnd {
  303. return common.All(r.rules, func(it *DefaultRule) bool {
  304. return it.Match(metadata)
  305. }) != r.invert
  306. } else {
  307. return common.Any(r.rules, func(it *DefaultRule) bool {
  308. return it.Match(metadata)
  309. }) != r.invert
  310. }
  311. }
  312. func (r *LogicalRule) Outbound() string {
  313. return r.outbound
  314. }
  315. func (r *LogicalRule) String() string {
  316. var op string
  317. switch r.mode {
  318. case C.LogicalTypeAnd:
  319. op = "&&"
  320. case C.LogicalTypeOr:
  321. op = "||"
  322. }
  323. if !r.invert {
  324. return strings.Join(F.MapToString(r.rules), " "+op+" ")
  325. } else {
  326. return "!(" + strings.Join(F.MapToString(r.rules), " "+op+" ") + ")"
  327. }
  328. }