rule_dns.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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 NewDNSRule(router adapter.Router, logger log.ContextLogger, options option.DNSRule) (adapter.DNSRule, 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.Server == "" {
  22. return nil, E.New("missing server field")
  23. }
  24. return NewDefaultDNSRule(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.Server == "" {
  30. return nil, E.New("missing server field")
  31. }
  32. return NewLogicalDNSRule(router, logger, options.LogicalOptions)
  33. default:
  34. return nil, E.New("unknown rule type: ", options.Type)
  35. }
  36. }
  37. var _ adapter.DNSRule = (*DefaultDNSRule)(nil)
  38. type DefaultDNSRule struct {
  39. items []RuleItem
  40. addressItems []RuleItem
  41. allItems []RuleItem
  42. invert bool
  43. outbound string
  44. disableCache bool
  45. }
  46. func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options option.DefaultDNSRule) (*DefaultDNSRule, error) {
  47. rule := &DefaultDNSRule{
  48. invert: options.Invert,
  49. outbound: options.Server,
  50. disableCache: options.DisableCache,
  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.Network != "" {
  58. switch options.Network {
  59. case C.NetworkTCP, C.NetworkUDP:
  60. item := NewNetworkItem(options.Network)
  61. rule.items = append(rule.items, item)
  62. rule.allItems = append(rule.allItems, item)
  63. default:
  64. return nil, E.New("invalid network: ", options.Network)
  65. }
  66. }
  67. if len(options.AuthUser) > 0 {
  68. item := NewAuthUserItem(options.AuthUser)
  69. rule.items = append(rule.items, item)
  70. rule.allItems = append(rule.allItems, item)
  71. }
  72. if len(options.Protocol) > 0 {
  73. item := NewProtocolItem(options.Protocol)
  74. rule.items = append(rule.items, item)
  75. rule.allItems = append(rule.allItems, item)
  76. }
  77. if len(options.Domain) > 0 || len(options.DomainSuffix) > 0 {
  78. item := NewDomainItem(options.Domain, options.DomainSuffix)
  79. rule.addressItems = append(rule.addressItems, item)
  80. rule.allItems = append(rule.allItems, item)
  81. }
  82. if len(options.DomainKeyword) > 0 {
  83. item := NewDomainKeywordItem(options.DomainKeyword)
  84. rule.addressItems = append(rule.addressItems, item)
  85. rule.allItems = append(rule.allItems, item)
  86. }
  87. if len(options.DomainRegex) > 0 {
  88. item, err := NewDomainRegexItem(options.DomainRegex)
  89. if err != nil {
  90. return nil, E.Cause(err, "domain_regex")
  91. }
  92. rule.addressItems = append(rule.addressItems, item)
  93. rule.allItems = append(rule.allItems, item)
  94. }
  95. if len(options.Geosite) > 0 {
  96. item := NewGeositeItem(router, logger, options.Geosite)
  97. rule.addressItems = append(rule.addressItems, item)
  98. rule.allItems = append(rule.allItems, item)
  99. }
  100. if len(options.SourceGeoIP) > 0 {
  101. item := NewGeoIPItem(router, logger, true, options.SourceGeoIP)
  102. rule.items = append(rule.items, item)
  103. rule.allItems = append(rule.allItems, item)
  104. }
  105. if len(options.SourceIPCIDR) > 0 {
  106. item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
  107. if err != nil {
  108. return nil, E.Cause(err, "source_ipcidr")
  109. }
  110. rule.items = append(rule.items, item)
  111. rule.allItems = append(rule.allItems, item)
  112. }
  113. if len(options.SourcePort) > 0 {
  114. item := NewPortItem(true, options.SourcePort)
  115. rule.items = append(rule.items, item)
  116. rule.allItems = append(rule.allItems, item)
  117. }
  118. if len(options.Port) > 0 {
  119. item := NewPortItem(false, options.Port)
  120. rule.items = append(rule.items, item)
  121. rule.allItems = append(rule.allItems, item)
  122. }
  123. if len(options.ProcessName) > 0 {
  124. item := NewProcessItem(options.ProcessName)
  125. rule.items = append(rule.items, item)
  126. rule.allItems = append(rule.allItems, item)
  127. }
  128. if len(options.PackageName) > 0 {
  129. item := NewPackageNameItem(options.PackageName)
  130. rule.items = append(rule.items, item)
  131. rule.allItems = append(rule.allItems, item)
  132. }
  133. if len(options.User) > 0 {
  134. item := NewUserItem(options.User)
  135. rule.items = append(rule.items, item)
  136. rule.allItems = append(rule.allItems, item)
  137. }
  138. if len(options.UserID) > 0 {
  139. item := NewUserIDItem(options.UserID)
  140. rule.items = append(rule.items, item)
  141. rule.allItems = append(rule.allItems, item)
  142. }
  143. if len(options.Outbound) > 0 {
  144. item := NewOutboundRule(options.Outbound)
  145. rule.items = append(rule.items, item)
  146. rule.allItems = append(rule.allItems, item)
  147. }
  148. return rule, nil
  149. }
  150. func (r *DefaultDNSRule) Type() string {
  151. return C.RuleTypeDefault
  152. }
  153. func (r *DefaultDNSRule) Start() error {
  154. for _, item := range r.allItems {
  155. err := common.Start(item)
  156. if err != nil {
  157. return err
  158. }
  159. }
  160. return nil
  161. }
  162. func (r *DefaultDNSRule) Close() error {
  163. for _, item := range r.allItems {
  164. err := common.Close(item)
  165. if err != nil {
  166. return err
  167. }
  168. }
  169. return nil
  170. }
  171. func (r *DefaultDNSRule) UpdateGeosite() error {
  172. for _, item := range r.allItems {
  173. if geositeItem, isSite := item.(*GeositeItem); isSite {
  174. err := geositeItem.Update()
  175. if err != nil {
  176. return err
  177. }
  178. }
  179. }
  180. return nil
  181. }
  182. func (r *DefaultDNSRule) Match(metadata *adapter.InboundContext) bool {
  183. for _, item := range r.items {
  184. if !item.Match(metadata) {
  185. return r.invert
  186. }
  187. }
  188. if len(r.addressItems) > 0 {
  189. var addressMatch bool
  190. for _, item := range r.addressItems {
  191. if item.Match(metadata) {
  192. addressMatch = true
  193. break
  194. }
  195. }
  196. if !addressMatch {
  197. return r.invert
  198. }
  199. }
  200. return !r.invert
  201. }
  202. func (r *DefaultDNSRule) Outbound() string {
  203. return r.outbound
  204. }
  205. func (r *DefaultDNSRule) DisableCache() bool {
  206. return r.disableCache
  207. }
  208. func (r *DefaultDNSRule) String() string {
  209. return strings.Join(F.MapToString(r.allItems), " ")
  210. }
  211. var _ adapter.DNSRule = (*LogicalDNSRule)(nil)
  212. type LogicalDNSRule struct {
  213. mode string
  214. rules []*DefaultDNSRule
  215. invert bool
  216. outbound string
  217. disableCache bool
  218. }
  219. func NewLogicalDNSRule(router adapter.Router, logger log.ContextLogger, options option.LogicalDNSRule) (*LogicalDNSRule, error) {
  220. r := &LogicalDNSRule{
  221. rules: make([]*DefaultDNSRule, len(options.Rules)),
  222. invert: options.Invert,
  223. outbound: options.Server,
  224. disableCache: options.DisableCache,
  225. }
  226. switch options.Mode {
  227. case C.LogicalTypeAnd:
  228. r.mode = C.LogicalTypeAnd
  229. case C.LogicalTypeOr:
  230. r.mode = C.LogicalTypeOr
  231. default:
  232. return nil, E.New("unknown logical mode: ", options.Mode)
  233. }
  234. for i, subRule := range options.Rules {
  235. rule, err := NewDefaultDNSRule(router, logger, subRule)
  236. if err != nil {
  237. return nil, E.Cause(err, "sub rule[", i, "]")
  238. }
  239. r.rules[i] = rule
  240. }
  241. return r, nil
  242. }
  243. func (r *LogicalDNSRule) Type() string {
  244. return C.RuleTypeLogical
  245. }
  246. func (r *LogicalDNSRule) UpdateGeosite() error {
  247. for _, rule := range r.rules {
  248. err := rule.UpdateGeosite()
  249. if err != nil {
  250. return err
  251. }
  252. }
  253. return nil
  254. }
  255. func (r *LogicalDNSRule) Start() error {
  256. for _, rule := range r.rules {
  257. err := rule.Start()
  258. if err != nil {
  259. return err
  260. }
  261. }
  262. return nil
  263. }
  264. func (r *LogicalDNSRule) Close() error {
  265. for _, rule := range r.rules {
  266. err := rule.Close()
  267. if err != nil {
  268. return err
  269. }
  270. }
  271. return nil
  272. }
  273. func (r *LogicalDNSRule) Match(metadata *adapter.InboundContext) bool {
  274. if r.mode == C.LogicalTypeAnd {
  275. return common.All(r.rules, func(it *DefaultDNSRule) bool {
  276. return it.Match(metadata)
  277. }) != r.invert
  278. } else {
  279. return common.Any(r.rules, func(it *DefaultDNSRule) bool {
  280. return it.Match(metadata)
  281. }) != r.invert
  282. }
  283. }
  284. func (r *LogicalDNSRule) Outbound() string {
  285. return r.outbound
  286. }
  287. func (r *LogicalDNSRule) DisableCache() bool {
  288. return r.disableCache
  289. }
  290. func (r *LogicalDNSRule) String() string {
  291. var op string
  292. switch r.mode {
  293. case C.LogicalTypeAnd:
  294. op = "&&"
  295. case C.LogicalTypeOr:
  296. op = "||"
  297. }
  298. if !r.invert {
  299. return strings.Join(F.MapToString(r.rules), " "+op+" ")
  300. } else {
  301. return "!(" + strings.Join(F.MapToString(r.rules), " "+op+" ") + ")"
  302. }
  303. }