mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2026-02-27 01:07:10 +00:00
feat: sniffer's force-domain and skip-domain support rule-set: and geosite:
This commit is contained in:
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/metacubex/mihomo/common/nnip"
|
||||
"github.com/metacubex/mihomo/component/profile/cachefile"
|
||||
"github.com/metacubex/mihomo/component/trie"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
)
|
||||
|
||||
@@ -36,8 +35,7 @@ type Pool struct {
|
||||
offset netip.Addr
|
||||
cycle bool
|
||||
mux sync.Mutex
|
||||
host *trie.DomainTrie[struct{}]
|
||||
rules []C.Rule
|
||||
host []C.Rule
|
||||
ipnet netip.Prefix
|
||||
store store
|
||||
}
|
||||
@@ -68,14 +66,8 @@ func (p *Pool) LookBack(ip netip.Addr) (string, bool) {
|
||||
|
||||
// ShouldSkipped return if domain should be skipped
|
||||
func (p *Pool) ShouldSkipped(domain string) bool {
|
||||
if p.host != nil {
|
||||
if p.host.Search(domain) != nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, rule := range p.rules {
|
||||
metadata := &C.Metadata{Host: domain}
|
||||
if match, _ := rule.Match(metadata); match {
|
||||
for _, rule := range p.host {
|
||||
if match, _ := rule.Match(&C.Metadata{Host: domain}); match {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -164,9 +156,7 @@ func (p *Pool) restoreState() {
|
||||
|
||||
type Options struct {
|
||||
IPNet netip.Prefix
|
||||
Host *trie.DomainTrie[struct{}]
|
||||
|
||||
Rules []C.Rule
|
||||
Host []C.Rule
|
||||
|
||||
// Size sets the maximum number of entries in memory
|
||||
// and does not work if Persistence is true
|
||||
@@ -197,7 +187,6 @@ func New(options Options) (*Pool, error) {
|
||||
offset: first.Prev(),
|
||||
cycle: false,
|
||||
host: options.Host,
|
||||
rules: options.Rules,
|
||||
ipnet: options.IPNet,
|
||||
}
|
||||
if options.Persistence {
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
|
||||
"github.com/metacubex/mihomo/component/profile/cachefile"
|
||||
"github.com/metacubex/mihomo/component/trie"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
RP "github.com/metacubex/mihomo/rules/provider"
|
||||
|
||||
"github.com/sagernet/bbolt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -154,7 +156,7 @@ func TestPool_Skip(t *testing.T) {
|
||||
pools, tempfile, err := createPools(Options{
|
||||
IPNet: ipnet,
|
||||
Size: 10,
|
||||
Host: tree,
|
||||
Host: []C.Rule{RP.NewDomainSet(tree.NewDomainSet(), "")},
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
defer os.Remove(tempfile)
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/metacubex/mihomo/common/lru"
|
||||
N "github.com/metacubex/mihomo/common/net"
|
||||
"github.com/metacubex/mihomo/component/trie"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/sniffer"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
@@ -26,17 +25,26 @@ var Dispatcher *SnifferDispatcher
|
||||
type SnifferDispatcher struct {
|
||||
enable bool
|
||||
sniffers map[sniffer.Sniffer]SnifferConfig
|
||||
forceDomain *trie.DomainSet
|
||||
skipSNI *trie.DomainSet
|
||||
forceDomain []C.Rule
|
||||
skipDomain []C.Rule
|
||||
skipList *lru.LruCache[string, uint8]
|
||||
forceDnsMapping bool
|
||||
parsePureIp bool
|
||||
}
|
||||
|
||||
func (sd *SnifferDispatcher) shouldOverride(metadata *C.Metadata) bool {
|
||||
return (metadata.Host == "" && sd.parsePureIp) ||
|
||||
sd.forceDomain.Has(metadata.Host) ||
|
||||
(metadata.DNSMode == C.DNSMapping && sd.forceDnsMapping)
|
||||
if metadata.Host == "" && sd.parsePureIp {
|
||||
return true
|
||||
}
|
||||
if metadata.DNSMode == C.DNSMapping && sd.forceDnsMapping {
|
||||
return true
|
||||
}
|
||||
for _, rule := range sd.forceDomain {
|
||||
if ok, _ := rule.Match(&C.Metadata{Host: metadata.Host}); ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (sd *SnifferDispatcher) UDPSniff(packet C.PacketAdapter) bool {
|
||||
@@ -94,9 +102,11 @@ func (sd *SnifferDispatcher) TCPSniff(conn *N.BufferedConn, metadata *C.Metadata
|
||||
log.Debugln("[Sniffer] All sniffing sniff failed with from [%s:%d] to [%s:%d]", metadata.SrcIP, metadata.SrcPort, metadata.String(), metadata.DstPort)
|
||||
return false
|
||||
} else {
|
||||
if sd.skipSNI.Has(host) {
|
||||
log.Debugln("[Sniffer] Skip sni[%s]", host)
|
||||
return false
|
||||
for _, rule := range sd.skipDomain {
|
||||
if ok, _ := rule.Match(&C.Metadata{Host: host}); ok {
|
||||
log.Debugln("[Sniffer] Skip sni[%s]", host)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
sd.skipList.Delete(dst)
|
||||
@@ -187,12 +197,12 @@ func NewCloseSnifferDispatcher() (*SnifferDispatcher, error) {
|
||||
}
|
||||
|
||||
func NewSnifferDispatcher(snifferConfig map[sniffer.Type]SnifferConfig,
|
||||
forceDomain *trie.DomainSet, skipSNI *trie.DomainSet,
|
||||
forceDomain []C.Rule, skipDomain []C.Rule,
|
||||
forceDnsMapping bool, parsePureIp bool) (*SnifferDispatcher, error) {
|
||||
dispatcher := SnifferDispatcher{
|
||||
enable: true,
|
||||
forceDomain: forceDomain,
|
||||
skipSNI: skipSNI,
|
||||
skipDomain: skipDomain,
|
||||
skipList: lru.New(lru.WithSize[string, uint8](128), lru.WithAge[string, uint8](600)),
|
||||
forceDnsMapping: forceDnsMapping,
|
||||
parsePureIp: parsePureIp,
|
||||
|
||||
@@ -134,6 +134,13 @@ func (t *DomainTrie[T]) Foreach(fn func(domain string, data T) bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *DomainTrie[T]) IsEmpty() bool {
|
||||
if t == nil {
|
||||
return true
|
||||
}
|
||||
return t.root.isEmpty()
|
||||
}
|
||||
|
||||
func recursion[T any](items []string, node *Node[T], fn func(domain string, data T) bool) bool {
|
||||
for key, data := range node.getChildren() {
|
||||
newItems := append([]string{key}, items...)
|
||||
|
||||
Reference in New Issue
Block a user