chore: Cache and skip multiple failed addresses
This commit is contained in:
parent
7b1427b843
commit
4948f3f213
1 changed files with 41 additions and 8 deletions
|
@ -2,10 +2,13 @@ package sniffer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/Dreamacro/clash/common/cache"
|
||||||
"github.com/Dreamacro/clash/constant/sniffer"
|
"github.com/Dreamacro/clash/constant/sniffer"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/component/trie"
|
"github.com/Dreamacro/clash/component/trie"
|
||||||
|
@ -33,6 +36,8 @@ type (
|
||||||
foreDomain *trie.DomainTrie[bool]
|
foreDomain *trie.DomainTrie[bool]
|
||||||
skipSNI *trie.DomainTrie[bool]
|
skipSNI *trie.DomainTrie[bool]
|
||||||
portRanges *[]utils.Range[uint16]
|
portRanges *[]utils.Range[uint16]
|
||||||
|
skipList *cache.LruCache[string, uint8]
|
||||||
|
rwMux sync.RWMutex
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -43,6 +48,7 @@ func (sd *SnifferDispatcher) TCPSniff(conn net.Conn, metadata *C.Metadata) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if metadata.Host == "" || sd.foreDomain.Search(metadata.Host) != nil {
|
if metadata.Host == "" || sd.foreDomain.Search(metadata.Host) != nil {
|
||||||
|
|
||||||
port, err := strconv.ParseUint(metadata.DstPort, 10, 16)
|
port, err := strconv.ParseUint(metadata.DstPort, 10, 16)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugln("[Sniffer] Dst port is error")
|
log.Debugln("[Sniffer] Dst port is error")
|
||||||
|
@ -61,7 +67,17 @@ func (sd *SnifferDispatcher) TCPSniff(conn net.Conn, metadata *C.Metadata) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sd.rwMux.RLock()
|
||||||
|
dst := fmt.Sprintf("%s:%s", metadata.DstIP, metadata.DstPort)
|
||||||
|
if count, ok := sd.skipList.Get(dst); ok && count > 5 {
|
||||||
|
log.Debugln("[Sniffer] Skip sniffing[%s] due to multiple failures", dst)
|
||||||
|
defer sd.rwMux.RUnlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sd.rwMux.RUnlock()
|
||||||
|
|
||||||
if host, err := sd.sniffDomain(bufConn, metadata); err != nil {
|
if host, err := sd.sniffDomain(bufConn, metadata); err != nil {
|
||||||
|
sd.cacheSniffFailed(metadata)
|
||||||
log.Debugln("[Sniffer] All sniffing sniff failed with from [%s:%s] to [%s:%s]", metadata.SrcIP, metadata.SrcPort, metadata.String(), metadata.DstPort)
|
log.Debugln("[Sniffer] All sniffing sniff failed with from [%s:%s] to [%s:%s]", metadata.SrcIP, metadata.SrcPort, metadata.String(), metadata.DstPort)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
|
@ -70,6 +86,10 @@ func (sd *SnifferDispatcher) TCPSniff(conn net.Conn, metadata *C.Metadata) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sd.rwMux.RLock()
|
||||||
|
sd.skipList.Delete(dst)
|
||||||
|
sd.rwMux.RUnlock()
|
||||||
|
|
||||||
sd.replaceDomain(metadata, host)
|
sd.replaceDomain(metadata, host)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,14 +115,15 @@ func (sd *SnifferDispatcher) Enable() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sd *SnifferDispatcher) sniffDomain(conn *CN.BufferedConn, metadata *C.Metadata) (string, error) {
|
func (sd *SnifferDispatcher) sniffDomain(conn *CN.BufferedConn, metadata *C.Metadata) (string, error) {
|
||||||
for _, sniffer := range sd.sniffers {
|
for _, s := range sd.sniffers {
|
||||||
if sniffer.SupportNetwork() == C.TCP {
|
if s.SupportNetwork() == C.TCP {
|
||||||
_ = conn.SetReadDeadline(time.Now().Add(3 * time.Second))
|
_ = conn.SetReadDeadline(time.Now().Add(1 * time.Second))
|
||||||
_, err := conn.Peek(1)
|
_, err := conn.Peek(1)
|
||||||
_ = conn.SetReadDeadline(time.Time{})
|
_ = conn.SetReadDeadline(time.Time{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_, ok := err.(*net.OpError)
|
_, ok := err.(*net.OpError)
|
||||||
if ok {
|
if ok {
|
||||||
|
sd.cacheSniffFailed(metadata)
|
||||||
log.Errorln("[Sniffer] [%s] may not have any sent data, Consider adding skip", metadata.DstIP.String())
|
log.Errorln("[Sniffer] [%s] may not have any sent data, Consider adding skip", metadata.DstIP.String())
|
||||||
_ = conn.Close()
|
_ = conn.Close()
|
||||||
}
|
}
|
||||||
|
@ -117,15 +138,15 @@ func (sd *SnifferDispatcher) sniffDomain(conn *CN.BufferedConn, metadata *C.Meta
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
host, err := sniffer.SniffTCP(bytes)
|
host, err := s.SniffTCP(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//log.Debugln("[Sniffer] [%s] Sniff data failed %s", sniffer.Protocol(), metadata.DstIP)
|
//log.Debugln("[Sniffer] [%s] Sniff data failed %s", s.Protocol(), metadata.DstIP)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = netip.ParseAddr(host)
|
_, err = netip.ParseAddr(host)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
//log.Debugln("[Sniffer] [%s] Sniff data failed %s", sniffer.Protocol(), metadata.DstIP)
|
//log.Debugln("[Sniffer] [%s] Sniff data failed %s", s.Protocol(), metadata.DstIP)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,6 +157,17 @@ func (sd *SnifferDispatcher) sniffDomain(conn *CN.BufferedConn, metadata *C.Meta
|
||||||
return "", ErrorSniffFailed
|
return "", ErrorSniffFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sd *SnifferDispatcher) cacheSniffFailed(metadata *C.Metadata) {
|
||||||
|
sd.rwMux.Lock()
|
||||||
|
dst := fmt.Sprintf("%s:%s", metadata.DstIP, metadata.DstPort)
|
||||||
|
count, _ := sd.skipList.Get(dst)
|
||||||
|
if count <= 5 {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
sd.skipList.Set(dst, count)
|
||||||
|
sd.rwMux.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
func NewCloseSnifferDispatcher() (*SnifferDispatcher, error) {
|
func NewCloseSnifferDispatcher() (*SnifferDispatcher, error) {
|
||||||
dispatcher := SnifferDispatcher{
|
dispatcher := SnifferDispatcher{
|
||||||
enable: false,
|
enable: false,
|
||||||
|
@ -151,16 +183,17 @@ func NewSnifferDispatcher(needSniffer []sniffer.Type, forceDomain *trie.DomainTr
|
||||||
foreDomain: forceDomain,
|
foreDomain: forceDomain,
|
||||||
skipSNI: skipSNI,
|
skipSNI: skipSNI,
|
||||||
portRanges: ports,
|
portRanges: ports,
|
||||||
|
skipList: cache.NewLRUCache[string, uint8](cache.WithSize[string, uint8](128), cache.WithAge[string, uint8](600)),
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, snifferName := range needSniffer {
|
for _, snifferName := range needSniffer {
|
||||||
sniffer, err := NewSniffer(snifferName)
|
s, err := NewSniffer(snifferName)
|
||||||
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 &SnifferDispatcher{enable: false}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatcher.sniffers = append(dispatcher.sniffers, sniffer)
|
dispatcher.sniffers = append(dispatcher.sniffers, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &dispatcher, nil
|
return &dispatcher, nil
|
||||||
|
|
Loading…
Reference in a new issue