rule_dns.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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.Logger, options option.DNSRule) (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.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.Rule = (*DefaultDNSRule)(nil)
  38. type DefaultDNSRule struct {
  39. items []RuleItem
  40. addressItems []RuleItem
  41. allItems []RuleItem
  42. outbound string
  43. }
  44. func NewDefaultDNSRule(router adapter.Router, logger log.Logger, options option.DefaultDNSRule) (*DefaultDNSRule, error) {
  45. rule := &DefaultDNSRule{
  46. outbound: options.Server,
  47. }
  48. if len(options.Inbound) > 0 {
  49. item := NewInboundRule(options.Inbound)
  50. rule.items = append(rule.items, item)
  51. rule.allItems = append(rule.allItems, item)
  52. }
  53. if options.Network != "" {
  54. switch options.Network {
  55. case C.NetworkTCP, C.NetworkUDP:
  56. item := NewNetworkItem(options.Network)
  57. rule.items = append(rule.items, item)
  58. rule.allItems = append(rule.allItems, item)
  59. default:
  60. return nil, E.New("invalid network: ", options.Network)
  61. }
  62. }
  63. if len(options.Protocol) > 0 {
  64. item := NewProtocolItem(options.Protocol)
  65. rule.items = append(rule.items, item)
  66. rule.allItems = append(rule.allItems, item)
  67. }
  68. if len(options.Domain) > 0 || len(options.DomainSuffix) > 0 {
  69. item := NewDomainItem(options.Domain, options.DomainSuffix)
  70. rule.addressItems = append(rule.addressItems, item)
  71. rule.allItems = append(rule.allItems, item)
  72. }
  73. if len(options.DomainKeyword) > 0 {
  74. item := NewDomainKeywordItem(options.DomainKeyword)
  75. rule.addressItems = append(rule.addressItems, item)
  76. rule.allItems = append(rule.allItems, item)
  77. }
  78. if len(options.DomainRegex) > 0 {
  79. item, err := NewDomainRegexItem(options.DomainRegex)
  80. if err != nil {
  81. return nil, E.Cause(err, "domain_regex")
  82. }
  83. rule.addressItems = append(rule.addressItems, item)
  84. rule.allItems = append(rule.allItems, item)
  85. }
  86. if len(options.Geosite) > 0 {
  87. item := NewGeositeItem(router, logger, options.Geosite)
  88. rule.addressItems = append(rule.addressItems, item)
  89. rule.allItems = append(rule.allItems, item)
  90. }
  91. if len(options.SourceGeoIP) > 0 {
  92. item := NewGeoIPItem(router, logger, true, options.SourceGeoIP)
  93. rule.items = append(rule.items, item)
  94. rule.allItems = append(rule.allItems, item)
  95. }
  96. if len(options.SourceIPCIDR) > 0 {
  97. item, err := NewIPCIDRItem(true, options.SourceIPCIDR)
  98. if err != nil {
  99. return nil, E.Cause(err, "source_ipcidr")
  100. }
  101. rule.items = append(rule.items, item)
  102. rule.allItems = append(rule.allItems, item)
  103. }
  104. if len(options.SourcePort) > 0 {
  105. item := NewPortItem(true, options.SourcePort)
  106. rule.items = append(rule.items, item)
  107. rule.allItems = append(rule.allItems, item)
  108. }
  109. if len(options.Port) > 0 {
  110. item := NewPortItem(false, options.Port)
  111. rule.items = append(rule.items, item)
  112. rule.allItems = append(rule.allItems, item)
  113. }
  114. if len(options.Outbound) > 0 {
  115. item := NewOutboundRule(options.Outbound)
  116. rule.items = append(rule.items, item)
  117. rule.allItems = append(rule.allItems, item)
  118. }
  119. return rule, nil
  120. }
  121. func (r *DefaultDNSRule) Start() error {
  122. for _, item := range r.allItems {
  123. err := common.Start(item)
  124. if err != nil {
  125. return err
  126. }
  127. }
  128. return nil
  129. }
  130. func (r *DefaultDNSRule) Close() error {
  131. for _, item := range r.allItems {
  132. err := common.Close(item)
  133. if err != nil {
  134. return err
  135. }
  136. }
  137. return nil
  138. }
  139. func (r *DefaultDNSRule) UpdateGeosite() error {
  140. for _, item := range r.allItems {
  141. if geositeItem, isSite := item.(*GeositeItem); isSite {
  142. err := geositeItem.Update()
  143. if err != nil {
  144. return err
  145. }
  146. }
  147. }
  148. return nil
  149. }
  150. func (r *DefaultDNSRule) Match(metadata *adapter.InboundContext) bool {
  151. for _, item := range r.items {
  152. if !item.Match(metadata) {
  153. return false
  154. }
  155. }
  156. if len(r.addressItems) > 0 {
  157. var addressMatch bool
  158. for _, item := range r.addressItems {
  159. if item.Match(metadata) {
  160. addressMatch = true
  161. break
  162. }
  163. }
  164. if !addressMatch {
  165. return false
  166. }
  167. }
  168. return true
  169. }
  170. func (r *DefaultDNSRule) Outbound() string {
  171. return r.outbound
  172. }
  173. func (r *DefaultDNSRule) String() string {
  174. return strings.Join(common.Map(r.allItems, F.ToString0[RuleItem]), " ")
  175. }
  176. var _ adapter.Rule = (*LogicalRule)(nil)
  177. type LogicalDNSRule struct {
  178. mode string
  179. rules []*DefaultDNSRule
  180. outbound string
  181. }
  182. func (r *LogicalDNSRule) UpdateGeosite() error {
  183. for _, rule := range r.rules {
  184. err := rule.UpdateGeosite()
  185. if err != nil {
  186. return err
  187. }
  188. }
  189. return nil
  190. }
  191. func (r *LogicalDNSRule) Start() error {
  192. for _, rule := range r.rules {
  193. err := rule.Start()
  194. if err != nil {
  195. return err
  196. }
  197. }
  198. return nil
  199. }
  200. func (r *LogicalDNSRule) Close() error {
  201. for _, rule := range r.rules {
  202. err := rule.Close()
  203. if err != nil {
  204. return err
  205. }
  206. }
  207. return nil
  208. }
  209. func NewLogicalDNSRule(router adapter.Router, logger log.Logger, options option.LogicalDNSRule) (*LogicalDNSRule, error) {
  210. r := &LogicalDNSRule{
  211. rules: make([]*DefaultDNSRule, len(options.Rules)),
  212. outbound: options.Server,
  213. }
  214. switch options.Mode {
  215. case C.LogicalTypeAnd:
  216. r.mode = C.LogicalTypeAnd
  217. case C.LogicalTypeOr:
  218. r.mode = C.LogicalTypeOr
  219. default:
  220. return nil, E.New("unknown logical mode: ", options.Mode)
  221. }
  222. for i, subRule := range options.Rules {
  223. rule, err := NewDefaultDNSRule(router, logger, subRule)
  224. if err != nil {
  225. return nil, E.Cause(err, "sub rule[", i, "]")
  226. }
  227. r.rules[i] = rule
  228. }
  229. return r, nil
  230. }
  231. func (r *LogicalDNSRule) Match(metadata *adapter.InboundContext) bool {
  232. if r.mode == C.LogicalTypeAnd {
  233. return common.All(r.rules, func(it *DefaultDNSRule) bool {
  234. return it.Match(metadata)
  235. })
  236. } else {
  237. return common.Any(r.rules, func(it *DefaultDNSRule) bool {
  238. return it.Match(metadata)
  239. })
  240. }
  241. }
  242. func (r *LogicalDNSRule) Outbound() string {
  243. return r.outbound
  244. }
  245. func (r *LogicalDNSRule) String() string {
  246. var op string
  247. switch r.mode {
  248. case C.LogicalTypeAnd:
  249. op = "&&"
  250. case C.LogicalTypeOr:
  251. op = "||"
  252. }
  253. return "logical(" + strings.Join(common.Map(r.rules, F.ToString0[*DefaultDNSRule]), " "+op+" ") + ")"
  254. }