github.com/yaling888/clash@v1.53.0/dns/filters.go (about)

     1  package dns
     2  
     3  import (
     4  	"net/netip"
     5  	"strings"
     6  
     7  	"github.com/yaling888/clash/component/geodata/router"
     8  	"github.com/yaling888/clash/component/mmdb"
     9  	"github.com/yaling888/clash/component/trie"
    10  )
    11  
    12  type fallbackIPFilter interface {
    13  	Match(netip.Addr) bool
    14  }
    15  
    16  type geoipFilter struct {
    17  	code string
    18  }
    19  
    20  func (gf *geoipFilter) Match(ip netip.Addr) bool {
    21  	record, _ := mmdb.Instance().Country(ip.AsSlice())
    22  	return !strings.EqualFold(record.Country.IsoCode, gf.code) && !ip.IsPrivate()
    23  }
    24  
    25  type ipnetFilter struct {
    26  	ipnet *netip.Prefix
    27  }
    28  
    29  func (inf *ipnetFilter) Match(ip netip.Addr) bool {
    30  	return inf.ipnet.Contains(ip)
    31  }
    32  
    33  type fallbackDomainFilter interface {
    34  	Match(domain string) bool
    35  }
    36  
    37  type domainFilter struct {
    38  	tree *trie.DomainTrie[bool]
    39  }
    40  
    41  func NewDomainFilter(domains []string) *domainFilter {
    42  	df := domainFilter{tree: trie.New[bool]()}
    43  	for _, domain := range domains {
    44  		_ = df.tree.Insert(domain, true)
    45  	}
    46  	return &df
    47  }
    48  
    49  func (df *domainFilter) Match(domain string) bool {
    50  	return df.tree.Search(domain) != nil
    51  }
    52  
    53  type geoSiteFilter struct {
    54  	matchers []*router.DomainMatcher
    55  }
    56  
    57  func (gsf *geoSiteFilter) Match(domain string) bool {
    58  	for _, matcher := range gsf.matchers {
    59  		if matcher.ApplyDomain(domain) {
    60  			return true
    61  		}
    62  	}
    63  	return false
    64  }