rule_dns.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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(router, options.ClashMode)
  214. rule.items = append(rule.items, item)
  215. rule.allItems = append(rule.allItems, item)
  216. }
  217. if len(options.WIFISSID) > 0 {
  218. item := NewWIFISSIDItem(networkManager, options.WIFISSID)
  219. rule.items = append(rule.items, item)
  220. rule.allItems = append(rule.allItems, item)
  221. }
  222. if len(options.WIFIBSSID) > 0 {
  223. item := NewWIFIBSSIDItem(networkManager, options.WIFIBSSID)
  224. rule.items = append(rule.items, item)
  225. rule.allItems = append(rule.allItems, item)
  226. }
  227. if len(options.RuleSet) > 0 {
  228. var matchSource bool
  229. if options.RuleSetIPCIDRMatchSource {
  230. matchSource = true
  231. } else
  232. //nolint:staticcheck
  233. if options.Deprecated_RulesetIPCIDRMatchSource {
  234. matchSource = true
  235. deprecated.Report(ctx, deprecated.OptionBadMatchSource)
  236. }
  237. item := NewRuleSetItem(router, options.RuleSet, matchSource, options.RuleSetIPCIDRAcceptEmpty)
  238. rule.items = append(rule.items, item)
  239. rule.allItems = append(rule.allItems, item)
  240. }
  241. return rule, nil
  242. }
  243. func (r *DefaultDNSRule) Action() adapter.RuleAction {
  244. return r.action
  245. }
  246. func (r *DefaultDNSRule) WithAddressLimit() bool {
  247. if len(r.destinationIPCIDRItems) > 0 {
  248. return true
  249. }
  250. for _, rawRule := range r.items {
  251. ruleSet, isRuleSet := rawRule.(*RuleSetItem)
  252. if !isRuleSet {
  253. continue
  254. }
  255. if ruleSet.ContainsDestinationIPCIDRRule() {
  256. return true
  257. }
  258. }
  259. return false
  260. }
  261. func (r *DefaultDNSRule) Match(metadata *adapter.InboundContext) bool {
  262. metadata.IgnoreDestinationIPCIDRMatch = true
  263. defer func() {
  264. metadata.IgnoreDestinationIPCIDRMatch = false
  265. }()
  266. return r.abstractDefaultRule.Match(metadata)
  267. }
  268. func (r *DefaultDNSRule) MatchAddressLimit(metadata *adapter.InboundContext) bool {
  269. return r.abstractDefaultRule.Match(metadata)
  270. }
  271. var _ adapter.DNSRule = (*LogicalDNSRule)(nil)
  272. type LogicalDNSRule struct {
  273. abstractLogicalRule
  274. }
  275. func NewLogicalDNSRule(ctx context.Context, logger log.ContextLogger, options option.LogicalDNSRule) (*LogicalDNSRule, error) {
  276. r := &LogicalDNSRule{
  277. abstractLogicalRule: abstractLogicalRule{
  278. rules: make([]adapter.HeadlessRule, len(options.Rules)),
  279. invert: options.Invert,
  280. action: NewDNSRuleAction(logger, options.DNSRuleAction),
  281. },
  282. }
  283. switch options.Mode {
  284. case C.LogicalTypeAnd:
  285. r.mode = C.LogicalTypeAnd
  286. case C.LogicalTypeOr:
  287. r.mode = C.LogicalTypeOr
  288. default:
  289. return nil, E.New("unknown logical mode: ", options.Mode)
  290. }
  291. for i, subRule := range options.Rules {
  292. rule, err := NewDNSRule(ctx, logger, subRule, false)
  293. if err != nil {
  294. return nil, E.Cause(err, "sub rule[", i, "]")
  295. }
  296. r.rules[i] = rule
  297. }
  298. return r, nil
  299. }
  300. func (r *LogicalDNSRule) Action() adapter.RuleAction {
  301. return r.action
  302. }
  303. func (r *LogicalDNSRule) WithAddressLimit() bool {
  304. for _, rawRule := range r.rules {
  305. switch rule := rawRule.(type) {
  306. case *DefaultDNSRule:
  307. if rule.WithAddressLimit() {
  308. return true
  309. }
  310. case *LogicalDNSRule:
  311. if rule.WithAddressLimit() {
  312. return true
  313. }
  314. }
  315. }
  316. return false
  317. }
  318. func (r *LogicalDNSRule) Match(metadata *adapter.InboundContext) bool {
  319. if r.mode == C.LogicalTypeAnd {
  320. return common.All(r.rules, func(it adapter.HeadlessRule) bool {
  321. metadata.ResetRuleCache()
  322. return it.(adapter.DNSRule).Match(metadata)
  323. }) != r.invert
  324. } else {
  325. return common.Any(r.rules, func(it adapter.HeadlessRule) bool {
  326. metadata.ResetRuleCache()
  327. return it.(adapter.DNSRule).Match(metadata)
  328. }) != r.invert
  329. }
  330. }
  331. func (r *LogicalDNSRule) MatchAddressLimit(metadata *adapter.InboundContext) bool {
  332. if r.mode == C.LogicalTypeAnd {
  333. return common.All(r.rules, func(it adapter.HeadlessRule) bool {
  334. metadata.ResetRuleCache()
  335. return it.(adapter.DNSRule).MatchAddressLimit(metadata)
  336. }) != r.invert
  337. } else {
  338. return common.Any(r.rules, func(it adapter.HeadlessRule) bool {
  339. metadata.ResetRuleCache()
  340. return it.(adapter.DNSRule).MatchAddressLimit(metadata)
  341. }) != r.invert
  342. }
  343. }