feat: sniff add skip-src-address and skip-dst-address

This commit is contained in:
wwqgtxx 2024-08-27 20:33:43 +08:00
parent 3e2c9ce821
commit 8483178524
6 changed files with 200 additions and 119 deletions

View File

@ -57,6 +57,10 @@ func (set *IpCidrSet) Merge() error {
return nil return nil
} }
func (set *IpCidrSet) IsEmpty() bool {
return set == nil || len(set.rr) == 0
}
func (set *IpCidrSet) Foreach(f func(prefix netip.Prefix) bool) { func (set *IpCidrSet) Foreach(f func(prefix netip.Prefix) bool) {
for _, r := range set.rr { for _, r := range set.rr {
for _, prefix := range r.Prefixes() { for _, prefix := range r.Prefixes() {

View File

@ -2,7 +2,6 @@ package sniffer
import ( import (
"errors" "errors"
"fmt"
"net" "net"
"net/netip" "net/netip"
"time" "time"
@ -20,19 +19,29 @@ var (
ErrNoClue = errors.New("not enough information for making a decision") ErrNoClue = errors.New("not enough information for making a decision")
) )
var Dispatcher *SnifferDispatcher type Dispatcher struct {
type SnifferDispatcher struct {
enable bool enable bool
sniffers map[sniffer.Sniffer]SnifferConfig sniffers map[sniffer.Sniffer]SnifferConfig
forceDomain []C.Rule forceDomain []C.Rule
skipSrcAddress []C.Rule
skipDstAddress []C.Rule
skipDomain []C.Rule skipDomain []C.Rule
skipList *lru.LruCache[string, uint8] skipList *lru.LruCache[netip.AddrPort, uint8]
forceDnsMapping bool forceDnsMapping bool
parsePureIp bool parsePureIp bool
} }
func (sd *SnifferDispatcher) shouldOverride(metadata *C.Metadata) bool { func (sd *Dispatcher) shouldOverride(metadata *C.Metadata) bool {
for _, rule := range sd.skipDstAddress {
if ok, _ := rule.Match(&C.Metadata{DstIP: metadata.DstIP}); ok {
return false
}
}
for _, rule := range sd.skipSrcAddress {
if ok, _ := rule.Match(&C.Metadata{DstIP: metadata.SrcIP}); ok {
return false
}
}
if metadata.Host == "" && sd.parsePureIp { if metadata.Host == "" && sd.parsePureIp {
return true return true
} }
@ -47,10 +56,9 @@ func (sd *SnifferDispatcher) shouldOverride(metadata *C.Metadata) bool {
return false return false
} }
func (sd *SnifferDispatcher) UDPSniff(packet C.PacketAdapter) bool { func (sd *Dispatcher) UDPSniff(packet C.PacketAdapter) bool {
metadata := packet.Metadata() metadata := packet.Metadata()
if sd.shouldOverride(metadata) {
if sd.shouldOverride(packet.Metadata()) {
for sniffer, config := range sd.sniffers { for sniffer, config := range sd.sniffers {
if sniffer.SupportNetwork() == C.UDP || sniffer.SupportNetwork() == C.ALLNet { if sniffer.SupportNetwork() == C.UDP || sniffer.SupportNetwork() == C.ALLNet {
inWhitelist := sniffer.SupportPort(metadata.DstPort) inWhitelist := sniffer.SupportPort(metadata.DstPort)
@ -73,7 +81,7 @@ func (sd *SnifferDispatcher) UDPSniff(packet C.PacketAdapter) bool {
} }
// TCPSniff returns true if the connection is sniffed to have a domain // TCPSniff returns true if the connection is sniffed to have a domain
func (sd *SnifferDispatcher) TCPSniff(conn *N.BufferedConn, metadata *C.Metadata) bool { func (sd *Dispatcher) TCPSniff(conn *N.BufferedConn, metadata *C.Metadata) bool {
if sd.shouldOverride(metadata) { if sd.shouldOverride(metadata) {
inWhitelist := false inWhitelist := false
overrideDest := false overrideDest := false
@ -91,34 +99,35 @@ func (sd *SnifferDispatcher) TCPSniff(conn *N.BufferedConn, metadata *C.Metadata
return false return false
} }
dst := fmt.Sprintf("%s:%d", metadata.DstIP, metadata.DstPort) dst := metadata.AddrPort()
if count, ok := sd.skipList.Get(dst); ok && count > 5 { if count, ok := sd.skipList.Get(dst); ok && count > 5 {
log.Debugln("[Sniffer] Skip sniffing[%s] due to multiple failures", dst) log.Debugln("[Sniffer] Skip sniffing[%s] due to multiple failures", dst)
return false return false
} }
if host, err := sd.sniffDomain(conn, metadata); err != nil { host, err := sd.sniffDomain(conn, metadata)
if err != nil {
sd.cacheSniffFailed(metadata) sd.cacheSniffFailed(metadata)
log.Debugln("[Sniffer] All sniffing sniff failed with from [%s:%d] to [%s:%d]", metadata.SrcIP, metadata.SrcPort, metadata.String(), metadata.DstPort) log.Debugln("[Sniffer] All sniffing sniff failed with from [%s:%d] to [%s:%d]", metadata.SrcIP, metadata.SrcPort, metadata.String(), metadata.DstPort)
return false return false
} else {
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)
sd.replaceDomain(metadata, host, overrideDest)
return true
} }
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)
sd.replaceDomain(metadata, host, overrideDest)
return true
} }
return false return false
} }
func (sd *SnifferDispatcher) replaceDomain(metadata *C.Metadata, host string, overrideDest bool) { func (sd *Dispatcher) replaceDomain(metadata *C.Metadata, host string, overrideDest bool) {
metadata.SniffHost = host metadata.SniffHost = host
if overrideDest { if overrideDest {
log.Debugln("[Sniffer] Sniff %s [%s]-->[%s] success, replace domain [%s]-->[%s]", log.Debugln("[Sniffer] Sniff %s [%s]-->[%s] success, replace domain [%s]-->[%s]",
@ -131,11 +140,11 @@ func (sd *SnifferDispatcher) replaceDomain(metadata *C.Metadata, host string, ov
metadata.DNSMode = C.DNSNormal metadata.DNSMode = C.DNSNormal
} }
func (sd *SnifferDispatcher) Enable() bool { func (sd *Dispatcher) Enable() bool {
return sd.enable return sd != nil && sd.enable
} }
func (sd *SnifferDispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metadata) (string, error) { func (sd *Dispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metadata) (string, error) {
for s := range sd.sniffers { for s := range sd.sniffers {
if s.SupportNetwork() == C.TCP { if s.SupportNetwork() == C.TCP {
_ = conn.SetReadDeadline(time.Now().Add(1 * time.Second)) _ = conn.SetReadDeadline(time.Now().Add(1 * time.Second))
@ -178,8 +187,8 @@ func (sd *SnifferDispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metad
return "", ErrorSniffFailed return "", ErrorSniffFailed
} }
func (sd *SnifferDispatcher) cacheSniffFailed(metadata *C.Metadata) { func (sd *Dispatcher) cacheSniffFailed(metadata *C.Metadata) {
dst := fmt.Sprintf("%s:%d", metadata.DstIP, metadata.DstPort) dst := metadata.AddrPort()
sd.skipList.Compute(dst, func(oldValue uint8, loaded bool) (newValue uint8, delete bool) { sd.skipList.Compute(dst, func(oldValue uint8, loaded bool) (newValue uint8, delete bool) {
if oldValue <= 5 { if oldValue <= 5 {
oldValue++ oldValue++
@ -188,32 +197,35 @@ func (sd *SnifferDispatcher) cacheSniffFailed(metadata *C.Metadata) {
}) })
} }
func NewCloseSnifferDispatcher() (*SnifferDispatcher, error) { type Config struct {
dispatcher := SnifferDispatcher{ Enable bool
enable: false, Sniffers map[sniffer.Type]SnifferConfig
} ForceDomain []C.Rule
SkipSrcAddress []C.Rule
return &dispatcher, nil SkipDstAddress []C.Rule
SkipDomain []C.Rule
ForceDnsMapping bool
ParsePureIp bool
} }
func NewSnifferDispatcher(snifferConfig map[sniffer.Type]SnifferConfig, func NewDispatcher(snifferConfig *Config) (*Dispatcher, error) {
forceDomain []C.Rule, skipDomain []C.Rule, dispatcher := Dispatcher{
forceDnsMapping bool, parsePureIp bool) (*SnifferDispatcher, error) { enable: snifferConfig.Enable,
dispatcher := SnifferDispatcher{ forceDomain: snifferConfig.ForceDomain,
enable: true, skipSrcAddress: snifferConfig.SkipSrcAddress,
forceDomain: forceDomain, skipDstAddress: snifferConfig.SkipDstAddress,
skipDomain: skipDomain, skipDomain: snifferConfig.SkipDomain,
skipList: lru.New(lru.WithSize[string, uint8](128), lru.WithAge[string, uint8](600)), skipList: lru.New(lru.WithSize[netip.AddrPort, uint8](128), lru.WithAge[netip.AddrPort, uint8](600)),
forceDnsMapping: forceDnsMapping, forceDnsMapping: snifferConfig.ForceDnsMapping,
parsePureIp: parsePureIp, parsePureIp: snifferConfig.ParsePureIp,
sniffers: make(map[sniffer.Sniffer]SnifferConfig, 0), sniffers: make(map[sniffer.Sniffer]SnifferConfig, len(snifferConfig.Sniffers)),
} }
for snifferName, config := range snifferConfig { for snifferName, config := range snifferConfig.Sniffers {
s, err := NewSniffer(snifferName, config) s, err := NewSniffer(snifferName, config)
if err != nil { if err != nil {
log.Errorln("Sniffer name[%s] is error", snifferName) log.Errorln("Sniffer name[%s] is error", snifferName)
return &SnifferDispatcher{enable: false}, err return &Dispatcher{enable: false}, err
} }
dispatcher.sniffers[s] = config dispatcher.sniffers[s] = config
} }

View File

@ -25,7 +25,7 @@ import (
"github.com/metacubex/mihomo/component/geodata" "github.com/metacubex/mihomo/component/geodata"
P "github.com/metacubex/mihomo/component/process" P "github.com/metacubex/mihomo/component/process"
"github.com/metacubex/mihomo/component/resolver" "github.com/metacubex/mihomo/component/resolver"
SNIFF "github.com/metacubex/mihomo/component/sniffer" "github.com/metacubex/mihomo/component/sniffer"
tlsC "github.com/metacubex/mihomo/component/tls" tlsC "github.com/metacubex/mihomo/component/tls"
"github.com/metacubex/mihomo/component/trie" "github.com/metacubex/mihomo/component/trie"
"github.com/metacubex/mihomo/component/updater" "github.com/metacubex/mihomo/component/updater"
@ -161,16 +161,6 @@ type Profile struct {
StoreFakeIP bool StoreFakeIP bool
} }
// Sniffer config
type Sniffer struct {
Enable bool
Sniffers map[snifferTypes.Type]SNIFF.SnifferConfig
ForceDomain []C.Rule
SkipDomain []C.Rule
ForceDnsMapping bool
ParsePureIp bool
}
// TLS config // TLS config
type TLS struct { type TLS struct {
Certificate string Certificate string
@ -196,7 +186,7 @@ type Config struct {
Providers map[string]providerTypes.ProxyProvider Providers map[string]providerTypes.ProxyProvider
RuleProviders map[string]providerTypes.RuleProvider RuleProviders map[string]providerTypes.RuleProvider
Tunnels []LC.Tunnel Tunnels []LC.Tunnel
Sniffer *Sniffer Sniffer *sniffer.Config
TLS *TLS TLS *TLS
} }
@ -327,15 +317,18 @@ type RawGeoXUrl struct {
} }
type RawSniffer struct { type RawSniffer struct {
Enable bool `yaml:"enable" json:"enable"` Enable bool `yaml:"enable" json:"enable"`
OverrideDest bool `yaml:"override-destination" json:"override-destination"` OverrideDest bool `yaml:"override-destination" json:"override-destination"`
Sniffing []string `yaml:"sniffing" json:"sniffing"` Sniffing []string `yaml:"sniffing" json:"sniffing"`
ForceDomain []string `yaml:"force-domain" json:"force-domain"` ForceDomain []string `yaml:"force-domain" json:"force-domain"`
SkipDomain []string `yaml:"skip-domain" json:"skip-domain"` SkipSrcAddress []string `yaml:"skip-src-address" json:"skip-src-address"`
Ports []string `yaml:"port-whitelist" json:"port-whitelist"` SkipDstAddress []string `yaml:"skip-dst-address" json:"skip-dst-address"`
ForceDnsMapping bool `yaml:"force-dns-mapping" json:"force-dns-mapping"` SkipDomain []string `yaml:"skip-domain" json:"skip-domain"`
ParsePureIp bool `yaml:"parse-pure-ip" json:"parse-pure-ip"` Ports []string `yaml:"port-whitelist" json:"port-whitelist"`
Sniff map[string]RawSniffingConfig `yaml:"sniff" json:"sniff"` ForceDnsMapping bool `yaml:"force-dns-mapping" json:"force-dns-mapping"`
ParsePureIp bool `yaml:"parse-pure-ip" json:"parse-pure-ip"`
Sniff map[string]RawSniffingConfig `yaml:"sniff" json:"sniff"`
} }
type RawSniffingConfig struct { type RawSniffingConfig struct {
@ -1477,7 +1470,7 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
var rule C.Rule var rule C.Rule
if len(cfg.Fallback) != 0 { if len(cfg.Fallback) != 0 {
if cfg.FallbackFilter.GeoIP { if cfg.FallbackFilter.GeoIP {
rule, err = RC.NewGEOIP(cfg.FallbackFilter.GeoIPCode, "", false, true) rule, err = RC.NewGEOIP(cfg.FallbackFilter.GeoIPCode, "dns.fallback-filter.geoip", false, true)
if err != nil { if err != nil {
return nil, fmt.Errorf("load GeoIP dns fallback filter error, %w", err) return nil, fmt.Errorf("load GeoIP dns fallback filter error, %w", err)
} }
@ -1507,7 +1500,7 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
} }
} }
rule = RP.NewDomainSet(domainTrie.NewDomainSet(), "dns.fallback-filter.domain") rule = RP.NewDomainSet(domainTrie.NewDomainSet(), "dns.fallback-filter.domain")
dnsCfg.FallbackIPFilter = append(dnsCfg.FallbackIPFilter, rule) dnsCfg.FallbackDomainFilter = append(dnsCfg.FallbackDomainFilter, rule)
} }
if len(cfg.FallbackFilter.GeoSite) > 0 { if len(cfg.FallbackFilter.GeoSite) > 0 {
log.Warnln("replace fallback-filter.geosite with nameserver-policy, it will be removed in the future") log.Warnln("replace fallback-filter.geosite with nameserver-policy, it will be removed in the future")
@ -1516,7 +1509,7 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul
if err != nil { if err != nil {
return nil, fmt.Errorf("DNS FallbackGeosite[%d] format error: %w", idx, err) return nil, fmt.Errorf("DNS FallbackGeosite[%d] format error: %w", idx, err)
} }
dnsCfg.FallbackIPFilter = append(dnsCfg.FallbackIPFilter, rule) dnsCfg.FallbackDomainFilter = append(dnsCfg.FallbackDomainFilter, rule)
} }
} }
} }
@ -1618,13 +1611,13 @@ func parseTuicServer(rawTuic RawTuicServer, general *General) error {
return nil return nil
} }
func parseSniffer(snifferRaw RawSniffer, ruleProviders map[string]providerTypes.RuleProvider) (*Sniffer, error) { func parseSniffer(snifferRaw RawSniffer, ruleProviders map[string]providerTypes.RuleProvider) (*sniffer.Config, error) {
sniffer := &Sniffer{ snifferConfig := &sniffer.Config{
Enable: snifferRaw.Enable, Enable: snifferRaw.Enable,
ForceDnsMapping: snifferRaw.ForceDnsMapping, ForceDnsMapping: snifferRaw.ForceDnsMapping,
ParsePureIp: snifferRaw.ParsePureIp, ParsePureIp: snifferRaw.ParsePureIp,
} }
loadSniffer := make(map[snifferTypes.Type]SNIFF.SnifferConfig) loadSniffer := make(map[snifferTypes.Type]sniffer.SnifferConfig)
if len(snifferRaw.Sniff) != 0 { if len(snifferRaw.Sniff) != 0 {
for sniffType, sniffConfig := range snifferRaw.Sniff { for sniffType, sniffConfig := range snifferRaw.Sniff {
@ -1640,7 +1633,7 @@ func parseSniffer(snifferRaw RawSniffer, ruleProviders map[string]providerTypes.
for _, snifferType := range snifferTypes.List { for _, snifferType := range snifferTypes.List {
if snifferType.String() == strings.ToUpper(sniffType) { if snifferType.String() == strings.ToUpper(sniffType) {
find = true find = true
loadSniffer[snifferType] = SNIFF.SnifferConfig{ loadSniffer[snifferType] = sniffer.SnifferConfig{
Ports: ports, Ports: ports,
OverrideDest: overrideDest, OverrideDest: overrideDest,
} }
@ -1652,7 +1645,7 @@ func parseSniffer(snifferRaw RawSniffer, ruleProviders map[string]providerTypes.
} }
} }
} else { } else {
if sniffer.Enable && len(snifferRaw.Sniffing) != 0 { if snifferConfig.Enable && len(snifferRaw.Sniffing) != 0 {
// Deprecated: Use Sniff instead // Deprecated: Use Sniff instead
log.Warnln("Deprecated: Use Sniff instead") log.Warnln("Deprecated: Use Sniff instead")
} }
@ -1666,7 +1659,7 @@ func parseSniffer(snifferRaw RawSniffer, ruleProviders map[string]providerTypes.
for _, snifferType := range snifferTypes.List { for _, snifferType := range snifferTypes.List {
if snifferType.String() == strings.ToUpper(snifferName) { if snifferType.String() == strings.ToUpper(snifferName) {
find = true find = true
loadSniffer[snifferType] = SNIFF.SnifferConfig{ loadSniffer[snifferType] = sniffer.SnifferConfig{
Ports: globalPorts, Ports: globalPorts,
OverrideDest: snifferRaw.OverrideDest, OverrideDest: snifferRaw.OverrideDest,
} }
@ -1679,21 +1672,80 @@ func parseSniffer(snifferRaw RawSniffer, ruleProviders map[string]providerTypes.
} }
} }
sniffer.Sniffers = loadSniffer snifferConfig.Sniffers = loadSniffer
forceDomain, err := parseDomain(snifferRaw.ForceDomain, nil, "sniffer.force-domain", ruleProviders) forceDomain, err := parseDomain(snifferRaw.ForceDomain, nil, "sniffer.force-domain", ruleProviders)
if err != nil { if err != nil {
return nil, fmt.Errorf("error in force-domain, error:%w", err) return nil, fmt.Errorf("error in force-domain, error:%w", err)
} }
sniffer.ForceDomain = forceDomain snifferConfig.ForceDomain = forceDomain
skipSrcAddress, err := parseIPCIDR(snifferRaw.SkipSrcAddress, nil, "sniffer.skip-src-address", ruleProviders)
if err != nil {
return nil, fmt.Errorf("error in skip-src-address, error:%w", err)
}
snifferConfig.SkipSrcAddress = skipSrcAddress
skipDstAddress, err := parseIPCIDR(snifferRaw.SkipDstAddress, nil, "sniffer.skip-src-address", ruleProviders)
if err != nil {
return nil, fmt.Errorf("error in skip-dst-address, error:%w", err)
}
snifferConfig.SkipDstAddress = skipDstAddress
skipDomain, err := parseDomain(snifferRaw.SkipDomain, nil, "sniffer.skip-domain", ruleProviders) skipDomain, err := parseDomain(snifferRaw.SkipDomain, nil, "sniffer.skip-domain", ruleProviders)
if err != nil { if err != nil {
return nil, fmt.Errorf("error in skip-domain, error:%w", err) return nil, fmt.Errorf("error in skip-domain, error:%w", err)
} }
sniffer.SkipDomain = skipDomain snifferConfig.SkipDomain = skipDomain
return sniffer, nil return snifferConfig, nil
}
func parseIPCIDR(addresses []string, cidrSet *cidr.IpCidrSet, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (ipRules []C.Rule, err error) {
var rule C.Rule
for _, ipcidr := range addresses {
ipcidrLower := strings.ToLower(ipcidr)
if strings.Contains(ipcidrLower, "geoip:") {
subkeys := strings.Split(ipcidr, ":")
subkeys = subkeys[1:]
subkeys = strings.Split(subkeys[0], ",")
for _, country := range subkeys {
rule, err = RC.NewGEOIP(country, adapterName, false, false)
if err != nil {
return nil, err
}
ipRules = append(ipRules, rule)
}
} else if strings.Contains(ipcidrLower, "rule-set:") {
subkeys := strings.Split(ipcidr, ":")
subkeys = subkeys[1:]
subkeys = strings.Split(subkeys[0], ",")
for _, domainSetName := range subkeys {
rule, err = parseIPRuleSet(domainSetName, adapterName, ruleProviders)
if err != nil {
return nil, err
}
ipRules = append(ipRules, rule)
}
} else {
if cidrSet == nil {
cidrSet = cidr.NewIpCidrSet()
}
err = cidrSet.AddIpCidrForString(ipcidr)
if err != nil {
return nil, err
}
}
}
if !cidrSet.IsEmpty() {
err = cidrSet.Merge()
if err != nil {
return nil, err
}
rule = RP.NewIpCidrSet(cidrSet, adapterName)
ipRules = append(ipRules, rule)
}
return
} }
func parseDomain(domains []string, domainTrie *trie.DomainTrie[struct{}], adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (domainRules []C.Rule, err error) { func parseDomain(domains []string, domainTrie *trie.DomainTrie[struct{}], adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (domainRules []C.Rule, err error) {
@ -1739,6 +1791,21 @@ func parseDomain(domains []string, domainTrie *trie.DomainTrie[struct{}], adapte
return return
} }
func parseIPRuleSet(domainSetName string, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (C.Rule, error) {
if rp, ok := ruleProviders[domainSetName]; !ok {
return nil, fmt.Errorf("not found rule-set: %s", domainSetName)
} else {
switch rp.Behavior() {
case providerTypes.Domain:
return nil, fmt.Errorf("rule provider type error, except ipcidr,actual %s", rp.Behavior())
case providerTypes.Classical:
log.Warnln("%s provider is %s, only matching it contain ip rule", rp.Name(), rp.Behavior())
default:
}
}
return RP.NewRuleSet(domainSetName, adapterName, true)
}
func parseDomainRuleSet(domainSetName string, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (C.Rule, error) { func parseDomainRuleSet(domainSetName string, adapterName string, ruleProviders map[string]providerTypes.RuleProvider) (C.Rule, error) {
if rp, ok := ruleProviders[domainSetName]; !ok { if rp, ok := ruleProviders[domainSetName]; !ok {
return nil, fmt.Errorf("not found rule-set: %s", domainSetName) return nil, fmt.Errorf("not found rule-set: %s", domainSetName)

View File

@ -190,6 +190,10 @@ sniffer:
override-destination: true override-destination: true
force-domain: force-domain:
- +.v2ex.com - +.v2ex.com
# skip-src-address: # 对于来源ip跳过嗅探
# - 192.168.0.3/32
# skip-dst-address: # 对于目标ip跳过嗅探
# - 192.168.0.3/32
## 对嗅探结果进行跳过 ## 对嗅探结果进行跳过
# skip-domain: # skip-domain:
# - Mijia Cloud # - Mijia Cloud

View File

@ -21,7 +21,7 @@ import (
"github.com/metacubex/mihomo/component/profile" "github.com/metacubex/mihomo/component/profile"
"github.com/metacubex/mihomo/component/profile/cachefile" "github.com/metacubex/mihomo/component/profile/cachefile"
"github.com/metacubex/mihomo/component/resolver" "github.com/metacubex/mihomo/component/resolver"
SNI "github.com/metacubex/mihomo/component/sniffer" "github.com/metacubex/mihomo/component/sniffer"
tlsC "github.com/metacubex/mihomo/component/tls" tlsC "github.com/metacubex/mihomo/component/tls"
"github.com/metacubex/mihomo/component/trie" "github.com/metacubex/mihomo/component/trie"
"github.com/metacubex/mihomo/component/updater" "github.com/metacubex/mihomo/component/updater"
@ -361,25 +361,17 @@ func hcCompatibleProvider(proxyProviders map[string]provider.ProxyProvider) {
} }
func updateSniffer(sniffer *config.Sniffer) { func updateSniffer(snifferConfig *sniffer.Config) {
if sniffer.Enable { dispatcher, err := sniffer.NewDispatcher(snifferConfig)
dispatcher, err := SNI.NewSnifferDispatcher( if err != nil {
sniffer.Sniffers, sniffer.ForceDomain, sniffer.SkipDomain, log.Warnln("initial sniffer failed, err:%v", err)
sniffer.ForceDnsMapping, sniffer.ParsePureIp, }
)
if err != nil {
log.Warnln("initial sniffer failed, err:%v", err)
}
tunnel.UpdateSniffer(dispatcher) tunnel.UpdateSniffer(dispatcher)
if snifferConfig.Enable {
log.Infoln("Sniffer is loaded and working") log.Infoln("Sniffer is loaded and working")
} else { } else {
dispatcher, err := SNI.NewCloseSnifferDispatcher()
if err != nil {
log.Warnln("initial sniffer failed, err:%v", err)
}
tunnel.UpdateSniffer(dispatcher)
log.Infoln("Sniffer is closed") log.Infoln("Sniffer is closed")
} }
} }

View File

@ -29,18 +29,17 @@ import (
) )
var ( var (
status = newAtomicStatus(Suspend) status = newAtomicStatus(Suspend)
tcpQueue = make(chan C.ConnContext, 200) tcpQueue = make(chan C.ConnContext, 200)
udpQueue = make(chan C.PacketAdapter, 200) udpQueue = make(chan C.PacketAdapter, 200)
natTable = nat.New() natTable = nat.New()
rules []C.Rule rules []C.Rule
listeners = make(map[string]C.InboundListener) listeners = make(map[string]C.InboundListener)
subRules map[string][]C.Rule subRules map[string][]C.Rule
proxies = make(map[string]C.Proxy) proxies = make(map[string]C.Proxy)
providers map[string]provider.ProxyProvider providers map[string]provider.ProxyProvider
ruleProviders map[string]provider.RuleProvider ruleProviders map[string]provider.RuleProvider
sniffingEnable = false configMux sync.RWMutex
configMux sync.RWMutex
// Outbound Rule // Outbound Rule
mode = Rule mode = Rule
@ -52,6 +51,9 @@ var (
fakeIPRange netip.Prefix fakeIPRange netip.Prefix
snifferDispatcher *sniffer.Dispatcher
sniffingEnable = false
ruleUpdateCallback = utils.NewCallback[provider.RuleProvider]() ruleUpdateCallback = utils.NewCallback[provider.RuleProvider]()
) )
@ -115,7 +117,7 @@ func FakeIPRange() netip.Prefix {
} }
func SetSniffing(b bool) { func SetSniffing(b bool) {
if sniffer.Dispatcher.Enable() { if snifferDispatcher.Enable() {
configMux.Lock() configMux.Lock()
sniffingEnable = b sniffingEnable = b
configMux.Unlock() configMux.Unlock()
@ -208,9 +210,9 @@ func UpdateListeners(newListeners map[string]C.InboundListener) {
listeners = newListeners listeners = newListeners
} }
func UpdateSniffer(dispatcher *sniffer.SnifferDispatcher) { func UpdateSniffer(dispatcher *sniffer.Dispatcher) {
configMux.Lock() configMux.Lock()
sniffer.Dispatcher = dispatcher snifferDispatcher = dispatcher
sniffingEnable = dispatcher.Enable() sniffingEnable = dispatcher.Enable()
configMux.Unlock() configMux.Unlock()
} }
@ -347,8 +349,8 @@ func handleUDPConn(packet C.PacketAdapter) {
return return
} }
if sniffer.Dispatcher.Enable() && sniffingEnable { if sniffingEnable && snifferDispatcher.Enable() {
sniffer.Dispatcher.UDPSniff(packet) snifferDispatcher.UDPSniff(packet)
} }
// local resolve UDP dns // local resolve UDP dns
@ -456,10 +458,10 @@ func handleTCPConn(connCtx C.ConnContext) {
conn := connCtx.Conn() conn := connCtx.Conn()
conn.ResetPeeked() // reset before sniffer conn.ResetPeeked() // reset before sniffer
if sniffer.Dispatcher.Enable() && sniffingEnable { if sniffingEnable && snifferDispatcher.Enable() {
// Try to sniff a domain when `preHandleMetadata` failed, this is usually // Try to sniff a domain when `preHandleMetadata` failed, this is usually
// caused by a "Fake DNS record missing" error when enhanced-mode is fake-ip. // caused by a "Fake DNS record missing" error when enhanced-mode is fake-ip.
if sniffer.Dispatcher.TCPSniff(conn, metadata) { if snifferDispatcher.TCPSniff(conn, metadata) {
// we now have a domain name // we now have a domain name
preHandleFailed = false preHandleFailed = false
} }