diff --git a/component/sniffer/dispatcher.go b/component/sniffer/dispatcher.go index a860914d..6f41db12 100644 --- a/component/sniffer/dispatcher.go +++ b/component/sniffer/dispatcher.go @@ -3,19 +3,18 @@ package sniffer import ( "errors" "fmt" - "github.com/Dreamacro/clash/common/cache" - "github.com/Dreamacro/clash/constant/sniffer" "net" "net/netip" "strconv" "sync" "time" - "github.com/Dreamacro/clash/component/trie" - - CN "github.com/Dreamacro/clash/common/net" + "github.com/Dreamacro/clash/common/cache" + N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/common/utils" + "github.com/Dreamacro/clash/component/trie" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/constant/sniffer" "github.com/Dreamacro/clash/log" ) @@ -25,30 +24,29 @@ var ( ErrNoClue = errors.New("not enough information for making a decision") ) -var Dispatcher SnifferDispatcher +var Dispatcher *SnifferDispatcher -type ( - SnifferDispatcher struct { - enable bool +type SnifferDispatcher struct { + enable bool - sniffers []sniffer.Sniffer + sniffers []sniffer.Sniffer - foreDomain *trie.DomainTrie[bool] - skipSNI *trie.DomainTrie[bool] - portRanges *[]utils.Range[uint16] - skipList *cache.LruCache[string, uint8] - rwMux sync.RWMutex - } -) + forceDomain *trie.DomainTrie[bool] + skipSNI *trie.DomainTrie[bool] + portRanges *[]utils.Range[uint16] + skipList *cache.LruCache[string, uint8] + rwMux sync.RWMutex + + forceDnsMapping bool +} func (sd *SnifferDispatcher) TCPSniff(conn net.Conn, metadata *C.Metadata) { - bufConn, ok := conn.(*CN.BufferedConn) + bufConn, ok := conn.(*N.BufferedConn) if !ok { return } - if metadata.Host == "" || sd.foreDomain.Search(metadata.Host) != nil { - + if metadata.Host == "" || sd.forceDomain.Search(metadata.Host) != nil || (metadata.DNSMode == C.DNSMapping && sd.forceDnsMapping) { port, err := strconv.ParseUint(metadata.DstPort, 10, 16) if err != nil { log.Debugln("[Sniffer] Dst port is error") @@ -114,7 +112,7 @@ func (sd *SnifferDispatcher) Enable() bool { return sd.enable } -func (sd *SnifferDispatcher) sniffDomain(conn *CN.BufferedConn, metadata *C.Metadata) (string, error) { +func (sd *SnifferDispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metadata) (string, error) { for _, s := range sd.sniffers { if s.SupportNetwork() == C.TCP { _ = conn.SetReadDeadline(time.Now().Add(1 * time.Second)) @@ -177,13 +175,14 @@ func NewCloseSnifferDispatcher() (*SnifferDispatcher, error) { } func NewSnifferDispatcher(needSniffer []sniffer.Type, forceDomain *trie.DomainTrie[bool], - skipSNI *trie.DomainTrie[bool], ports *[]utils.Range[uint16]) (*SnifferDispatcher, error) { + skipSNI *trie.DomainTrie[bool], ports *[]utils.Range[uint16], forceDnsMapping bool) (*SnifferDispatcher, error) { dispatcher := SnifferDispatcher{ - enable: true, - foreDomain: forceDomain, - skipSNI: skipSNI, - portRanges: ports, - skipList: cache.NewLRUCache[string, uint8](cache.WithSize[string, uint8](128), cache.WithAge[string, uint8](600)), + enable: true, + forceDomain: forceDomain, + skipSNI: skipSNI, + portRanges: ports, + skipList: cache.NewLRUCache[string, uint8](cache.WithSize[string, uint8](128), cache.WithAge[string, uint8](600)), + forceDnsMapping: forceDnsMapping, } for _, snifferName := range needSniffer { diff --git a/component/sniffer/http_sniffer.go b/component/sniffer/http_sniffer.go index f75285ed..551b20c8 100644 --- a/component/sniffer/http_sniffer.go +++ b/component/sniffer/http_sniffer.go @@ -4,9 +4,10 @@ import ( "bytes" "errors" "fmt" - C "github.com/Dreamacro/clash/constant" "net" "strings" + + C "github.com/Dreamacro/clash/constant" ) var ( diff --git a/config/config.go b/config/config.go index 8d263939..b9c3d863 100644 --- a/config/config.go +++ b/config/config.go @@ -195,12 +195,13 @@ type IPTables struct { } type Sniffer struct { - Enable bool - Sniffers []sniffer.Type - Reverses *trie.DomainTrie[bool] - ForceDomain *trie.DomainTrie[bool] - SkipDomain *trie.DomainTrie[bool] - Ports *[]utils.Range[uint16] + Enable bool + Sniffers []sniffer.Type + Reverses *trie.DomainTrie[bool] + ForceDomain *trie.DomainTrie[bool] + SkipDomain *trie.DomainTrie[bool] + Ports *[]utils.Range[uint16] + ForceDnsMapping bool } // Experimental config @@ -325,11 +326,12 @@ type RawGeoXUrl struct { } type RawSniffer struct { - Enable bool `yaml:"enable" json:"enable"` - Sniffing []string `yaml:"sniffing" json:"sniffing"` - ForceDomain []string `yaml:"force-domain" json:"force-domain"` - SkipDomain []string `yaml:"skip-domain" json:"skip-domain"` - Ports []string `yaml:"port-whitelist" json:"port-whitelist"` + Enable bool `yaml:"enable" json:"enable"` + Sniffing []string `yaml:"sniffing" json:"sniffing"` + ForceDomain []string `yaml:"force-domain" json:"force-domain"` + SkipDomain []string `yaml:"skip-domain" json:"skip-domain"` + Ports []string `yaml:"port-whitelist" json:"port-whitelist"` + ForceDnsMapping bool `yaml:"force-dns-mapping" json:"force-dns-mapping"` } // EBpf config @@ -419,11 +421,12 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) { }, }, Sniffer: RawSniffer{ - Enable: false, - Sniffing: []string{}, - ForceDomain: []string{}, - SkipDomain: []string{}, - Ports: []string{}, + Enable: false, + Sniffing: []string{}, + ForceDomain: []string{}, + SkipDomain: []string{}, + Ports: []string{}, + ForceDnsMapping: true, }, Profile: Profile{ StoreSelected: true, @@ -1173,7 +1176,8 @@ func parseTun(rawTun RawTun, general *General, dnsCfg *DNS) (*Tun, error) { func parseSniffer(snifferRaw RawSniffer) (*Sniffer, error) { sniffer := &Sniffer{ - Enable: snifferRaw.Enable, + Enable: snifferRaw.Enable, + ForceDnsMapping: snifferRaw.ForceDnsMapping, } var ports []utils.Range[uint16] diff --git a/context/conn.go b/context/conn.go index 00a125f3..08bbe3c7 100644 --- a/context/conn.go +++ b/context/conn.go @@ -1,10 +1,11 @@ package context import ( - CN "github.com/Dreamacro/clash/common/net" "net" + N "github.com/Dreamacro/clash/common/net" C "github.com/Dreamacro/clash/constant" + "github.com/gofrs/uuid" ) @@ -20,7 +21,7 @@ func NewConnContext(conn net.Conn, metadata *C.Metadata) *ConnContext { return &ConnContext{ id: id, metadata: metadata, - conn: CN.NewBufferedConn(conn), + conn: N.NewBufferedConn(conn), } } diff --git a/hub/executor/executor.go b/hub/executor/executor.go index a8999e36..6efb3654 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -265,7 +265,7 @@ func updateTun(tun *config.Tun) { func updateSniffer(sniffer *config.Sniffer) { if sniffer.Enable { - dispatcher, err := SNI.NewSnifferDispatcher(sniffer.Sniffers, sniffer.ForceDomain, sniffer.SkipDomain, sniffer.Ports) + dispatcher, err := SNI.NewSnifferDispatcher(sniffer.Sniffers, sniffer.ForceDomain, sniffer.SkipDomain, sniffer.Ports, sniffer.ForceDnsMapping) if err != nil { log.Warnln("initial sniffer failed, err:%v", err) } diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 92615900..2aa072ec 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -107,7 +107,7 @@ func UpdateProxies(newProxies map[string]C.Proxy, newProviders map[string]provid func UpdateSniffer(dispatcher *sniffer.SnifferDispatcher) { configMux.Lock() - sniffer.Dispatcher = *dispatcher + sniffer.Dispatcher = dispatcher sniffingEnable = true configMux.Unlock() }