rule_item_domain.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package rule
  2. import (
  3. "strings"
  4. "github.com/sagernet/sing-box/adapter"
  5. "github.com/sagernet/sing/common/domain"
  6. E "github.com/sagernet/sing/common/exceptions"
  7. )
  8. var _ RuleItem = (*DomainItem)(nil)
  9. type DomainItem struct {
  10. matcher *domain.Matcher
  11. description string
  12. }
  13. func NewDomainItem(domains []string, domainSuffixes []string) (*DomainItem, error) {
  14. for _, domainItem := range domains {
  15. if domainItem == "" {
  16. return nil, E.New("domain: empty item is not allowed")
  17. }
  18. }
  19. for _, domainSuffixItem := range domainSuffixes {
  20. if domainSuffixItem == "" {
  21. return nil, E.New("domain_suffix: empty item is not allowed")
  22. }
  23. }
  24. var description string
  25. if dLen := len(domains); dLen > 0 {
  26. if dLen == 1 {
  27. description = "domain=" + domains[0]
  28. } else if dLen > 3 {
  29. description = "domain=[" + strings.Join(domains[:3], " ") + "...]"
  30. } else {
  31. description = "domain=[" + strings.Join(domains, " ") + "]"
  32. }
  33. }
  34. if dsLen := len(domainSuffixes); dsLen > 0 {
  35. if len(description) > 0 {
  36. description += " "
  37. }
  38. if dsLen == 1 {
  39. description += "domain_suffix=" + domainSuffixes[0]
  40. } else if dsLen > 3 {
  41. description += "domain_suffix=[" + strings.Join(domainSuffixes[:3], " ") + "...]"
  42. } else {
  43. description += "domain_suffix=[" + strings.Join(domainSuffixes, " ") + "]"
  44. }
  45. }
  46. return &DomainItem{
  47. domain.NewMatcher(domains, domainSuffixes, false),
  48. description,
  49. }, nil
  50. }
  51. func NewRawDomainItem(matcher *domain.Matcher) *DomainItem {
  52. return &DomainItem{
  53. matcher,
  54. "domain/domain_suffix=<binary>",
  55. }
  56. }
  57. func (r *DomainItem) Match(metadata *adapter.InboundContext) bool {
  58. var domainHost string
  59. if metadata.Domain != "" {
  60. domainHost = metadata.Domain
  61. } else {
  62. domainHost = metadata.Destination.Fqdn
  63. }
  64. if domainHost == "" {
  65. return false
  66. }
  67. return r.matcher.Match(strings.ToLower(domainHost))
  68. }
  69. func (r *DomainItem) String() string {
  70. return r.description
  71. }