rule_dns.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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 NewDNSRule(ctx context.Context, logger log.ContextLogger, options option.DNSRule, checkServer bool) (adapter.DNSRule, 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.Server == "" && checkServer {
  22. return nil, E.New("missing server field")
  23. }
  24. }
  25. return NewDefaultDNSRule(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.Server == "" && checkServer {
  33. return nil, E.New("missing server field")
  34. }
  35. }
  36. return NewLogicalDNSRule(ctx, logger, options.LogicalOptions)
  37. default:
  38. return nil, E.New("unknown rule type: ", options.Type)
  39. }
  40. }
  41. var _ adapter.DNSRule = (*DefaultDNSRule)(nil)
  42. type DefaultDNSRule struct {
  43. abstractDefaultRule
  44. }
  45. func NewDefaultDNSRule(ctx context.Context, logger log.ContextLogger, options option.DefaultDNSRule) (*DefaultDNSRule, error) {
  46. rule := &DefaultDNSRule{
  47. abstractDefaultRule: abstractDefaultRule{
  48. invert: options.Invert,
  49. action: NewDNSRuleAction(logger, options.DNSRuleAction),
  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. router := service.FromContext[adapter.Router](ctx)
  58. networkManager := service.FromContext[adapter.NetworkManager](ctx)
  59. if options.IPVersion > 0 {
  60. switch options.IPVersion {
  61. case 4, 6:
  62. item := NewIPVersionItem(options.IPVersion == 6)
  63. rule.items = append(rule.items, item)
  64. rule.allItems = append(rule.allItems, item)
  65. default:
  66. return nil, E.New("invalid ip version: ", options.IPVersion)
  67. }
  68. }
  69. if len(options.QueryType) > 0 {
  70. item := NewQueryTypeItem(options.QueryType)
  71. rule.items = append(rule.items, item)
  72. rule.allItems = append(rule.allItems, item)
  73. }
  74. if len(options.Network) > 0 {
  75. item := NewNetworkItem(options.Network)
  76. rule.items = append(rule.items, item)
  77. rule.allItems = append(rule.allItems, item)
  78. }
  79. if len(options.AuthUser) > 0 {
  80. item := NewAuthUserItem(options.AuthUser)
  81. rule.items = append(rule.items, item)
  82. rule.allItems = append(rule.allItems, item)
  83. }
  84. if len(options.Protocol) > 0 {
  85. item := NewProtocolItem(options.Protocol)
  86. rule.items = append(rule.items, item)
  87. rule.allItems = append(rule.allItems, item)
  88. }
  89. if len(options.Domain) > 0 || len(options.DomainSuffix) > 0 {
  90. item := NewDomainItem(options.Domain, options.DomainSuffix)
  91. rule.destinationAddressItems = append(rule.destinationAddressItems, item)
  92. rule.allItems = append(rule.allItems, item)
  93. }
  94. if len(options.DomainKeyword) > 0 {
  95. item := NewDomainKeywordItem(options.DomainKeyword)
  96. rule.destinationAddressItems = append(rule.destinationAddressItems, item)
  97. rule.allItems = append(rule.allItems, item)
  98. }
  99. if len(options.DomainRegex) > 0 {
  100. item, err := NewDomainRegexItem(options.DomainRegex)
  101. if err != nil {
  102. return nil, E.Cause(err, "domain_regex")
  103. }
  104. rule.destinationAddressItems = append(rule.destinationAddressItems, item)
  105. rule.allItems = append(rule.allItems, item)
  106. }
  107. if len(options.Geosite) > 0 {
  108. item := NewGeositeItem(router, logger, options.Geosite)
  109. rule.destinationAddressItems = append(rule.destinationAddressItems, item)
  110. rule.allItems = append(rule.allItems, item)
  111. }
  112. if len(options.SourceGeoIP) > 0 {
  113. item := NewGeoIPItem(router, logger, true, options.SourceGeoIP)
  114. rule.sourceAddressItems = append(rule.sourceAddressItems, item)
  115. rule.allItems = append(rule.allItems, item)
  116. }
  117. if len(options.GeoIP) > 0 {
  118. item := NewGeoIPItem(router, logger, false, options.GeoIP)
  119. rule.destinationIPCIDRItems = append(rule.destinationIPCIDRItems, item)
  120. rule.allItems = append(rule.allItems, item)
  121. }
  122. if len(options.SourceIPCIDR) > 0 {
  123. item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
  124. if err != nil {
  125. return nil, E.Cause(err, "source_ip_cidr")
  126. }
  127. rule.sourceAddressItems = append(rule.sourceAddressItems, item)
  128. rule.allItems = append(rule.allItems, item)
  129. }
  130. if len(options.IPCIDR) > 0 {
  131. item, err := NewIPCIDRItem(false, options.IPCIDR)
  132. if err != nil {
  133. return nil, E.Cause(err, "ip_cidr")
  134. }
  135. rule.destinationIPCIDRItems = append(rule.destinationIPCIDRItems, item)
  136. rule.allItems = append(rule.allItems, item)
  137. }
  138. if options.SourceIPIsPrivate {
  139. item := NewIPIsPrivateItem(true)
  140. rule.sourceAddressItems = append(rule.sourceAddressItems, item)
  141. rule.allItems = append(rule.allItems, item)
  142. }
  143. if options.IPIsPrivate {
  144. item := NewIPIsPrivateItem(false)
  145. rule.destinationIPCIDRItems = append(rule.destinationIPCIDRItems, item)
  146. rule.allItems = append(rule.allItems, item)
  147. }
  148. if len(options.SourcePort) > 0 {
  149. item := NewPortItem(true, options.SourcePort)
  150. rule.sourcePortItems = append(rule.sourcePortItems, item)
  151. rule.allItems = append(rule.allItems, item)
  152. }
  153. if len(options.SourcePortRange) > 0 {
  154. item, err := NewPortRangeItem(true, options.SourcePortRange)
  155. if err != nil {
  156. return nil, E.Cause(err, "source_port_range")
  157. }
  158. rule.sourcePortItems = append(rule.sourcePortItems, item)
  159. rule.allItems = append(rule.allItems, item)
  160. }
  161. if len(options.Port) > 0 {
  162. item := NewPortItem(false, options.Port)
  163. rule.destinationPortItems = append(rule.destinationPortItems, item)
  164. rule.allItems = append(rule.allItems, item)
  165. }
  166. if len(options.PortRange) > 0 {
  167. item, err := NewPortRangeItem(false, options.PortRange)
  168. if err != nil {
  169. return nil, E.Cause(err, "port_range")
  170. }
  171. rule.destinationPortItems = append(rule.destinationPortItems, item)
  172. rule.allItems = append(rule.allItems, item)
  173. }
  174. if len(options.ProcessName) > 0 {
  175. item := NewProcessItem(options.ProcessName)
  176. rule.items = append(rule.items, item)
  177. rule.allItems = append(rule.allItems, item)
  178. }
  179. if len(options.ProcessPath) > 0 {
  180. item := NewProcessPathItem(options.ProcessPath)
  181. rule.items = append(rule.items, item)
  182. rule.allItems = append(rule.allItems, item)
  183. }
  184. if len(options.ProcessPathRegex) > 0 {
  185. item, err := NewProcessPathRegexItem(options.ProcessPathRegex)
  186. if err != nil {
  187. return nil, E.Cause(err, "process_path_regex")
  188. }
  189. rule.items = append(rule.items, item)
  190. rule.allItems = append(rule.allItems, item)
  191. }
  192. if len(options.PackageName) > 0 {
  193. item := NewPackageNameItem(options.PackageName)
  194. rule.items = append(rule.items, item)
  195. rule.allItems = append(rule.allItems, item)
  196. }
  197. if len(options.User) > 0 {
  198. item := NewUserItem(options.User)
  199. rule.items = append(rule.items, item)
  200. rule.allItems = append(rule.allItems, item)
  201. }
  202. if len(options.UserID) > 0 {
  203. item := NewUserIDItem(options.UserID)
  204. rule.items = append(rule.items, item)
  205. rule.allItems = append(rule.allItems, item)
  206. }
  207. if len(options.Outbound) > 0 {
  208. item := NewOutboundRule(options.Outbound)
  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, options.NetworkType)
  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 len(options.RuleSet) > 0 {
  243. var matchSource bool
  244. if options.RuleSetIPCIDRMatchSource {
  245. matchSource = true
  246. } else
  247. //nolint:staticcheck
  248. if options.Deprecated_RulesetIPCIDRMatchSource {
  249. matchSource = true
  250. deprecated.Report(ctx, deprecated.OptionBadMatchSource)
  251. }
  252. item := NewRuleSetItem(router, options.RuleSet, matchSource, options.RuleSetIPCIDRAcceptEmpty)
  253. rule.items = append(rule.items, item)
  254. rule.allItems = append(rule.allItems, item)
  255. }
  256. return rule, nil
  257. }
  258. func (r *DefaultDNSRule) Action() adapter.RuleAction {
  259. return r.action
  260. }
  261. func (r *DefaultDNSRule) WithAddressLimit() bool {
  262. if len(r.destinationIPCIDRItems) > 0 {
  263. return true
  264. }
  265. for _, rawRule := range r.items {
  266. ruleSet, isRuleSet := rawRule.(*RuleSetItem)
  267. if !isRuleSet {
  268. continue
  269. }
  270. if ruleSet.ContainsDestinationIPCIDRRule() {
  271. return true
  272. }
  273. }
  274. return false
  275. }
  276. func (r *DefaultDNSRule) Match(metadata *adapter.InboundContext) bool {
  277. metadata.IgnoreDestinationIPCIDRMatch = true
  278. defer func() {
  279. metadata.IgnoreDestinationIPCIDRMatch = false
  280. }()
  281. return r.abstractDefaultRule.Match(metadata)
  282. }
  283. func (r *DefaultDNSRule) MatchAddressLimit(metadata *adapter.InboundContext) bool {
  284. return r.abstractDefaultRule.Match(metadata)
  285. }
  286. var _ adapter.DNSRule = (*LogicalDNSRule)(nil)
  287. type LogicalDNSRule struct {
  288. abstractLogicalRule
  289. }
  290. func NewLogicalDNSRule(ctx context.Context, logger log.ContextLogger, options option.LogicalDNSRule) (*LogicalDNSRule, error) {
  291. r := &LogicalDNSRule{
  292. abstractLogicalRule: abstractLogicalRule{
  293. rules: make([]adapter.HeadlessRule, len(options.Rules)),
  294. invert: options.Invert,
  295. action: NewDNSRuleAction(logger, options.DNSRuleAction),
  296. },
  297. }
  298. switch options.Mode {
  299. case C.LogicalTypeAnd:
  300. r.mode = C.LogicalTypeAnd
  301. case C.LogicalTypeOr:
  302. r.mode = C.LogicalTypeOr
  303. default:
  304. return nil, E.New("unknown logical mode: ", options.Mode)
  305. }
  306. for i, subRule := range options.Rules {
  307. rule, err := NewDNSRule(ctx, logger, subRule, false)
  308. if err != nil {
  309. return nil, E.Cause(err, "sub rule[", i, "]")
  310. }
  311. r.rules[i] = rule
  312. }
  313. return r, nil
  314. }
  315. func (r *LogicalDNSRule) Action() adapter.RuleAction {
  316. return r.action
  317. }
  318. func (r *LogicalDNSRule) WithAddressLimit() bool {
  319. for _, rawRule := range r.rules {
  320. switch rule := rawRule.(type) {
  321. case *DefaultDNSRule:
  322. if rule.WithAddressLimit() {
  323. return true
  324. }
  325. case *LogicalDNSRule:
  326. if rule.WithAddressLimit() {
  327. return true
  328. }
  329. }
  330. }
  331. return false
  332. }
  333. func (r *LogicalDNSRule) Match(metadata *adapter.InboundContext) bool {
  334. if r.mode == C.LogicalTypeAnd {
  335. return common.All(r.rules, func(it adapter.HeadlessRule) bool {
  336. metadata.ResetRuleCache()
  337. return it.(adapter.DNSRule).Match(metadata)
  338. }) != r.invert
  339. } else {
  340. return common.Any(r.rules, func(it adapter.HeadlessRule) bool {
  341. metadata.ResetRuleCache()
  342. return it.(adapter.DNSRule).Match(metadata)
  343. }) != r.invert
  344. }
  345. }
  346. func (r *LogicalDNSRule) MatchAddressLimit(metadata *adapter.InboundContext) bool {
  347. if r.mode == C.LogicalTypeAnd {
  348. return common.All(r.rules, func(it adapter.HeadlessRule) bool {
  349. metadata.ResetRuleCache()
  350. return it.(adapter.DNSRule).MatchAddressLimit(metadata)
  351. }) != r.invert
  352. } else {
  353. return common.Any(r.rules, func(it adapter.HeadlessRule) bool {
  354. metadata.ResetRuleCache()
  355. return it.(adapter.DNSRule).MatchAddressLimit(metadata)
  356. }) != r.invert
  357. }
  358. }