feat: sniffer support
sniffer: enable: true force: false # Overwrite domain sniffing: - tls
This commit is contained in:
104
component/sniffer/dispatcher.go
Normal file
104
component/sniffer/dispatcher.go
Normal file
@ -0,0 +1,104 @@
|
||||
package sniffer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
|
||||
CN "github.com/Dreamacro/clash/common/net"
|
||||
"github.com/Dreamacro/clash/component/resolver"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrorUnsupportedSniffer = errors.New("unsupported sniffer")
|
||||
)
|
||||
|
||||
var Dispatcher SnifferDispatcher
|
||||
|
||||
type SnifferDispatcher struct {
|
||||
enable bool
|
||||
force bool
|
||||
sniffers []C.Sniffer
|
||||
}
|
||||
|
||||
func (sd *SnifferDispatcher) Tcp(conn net.Conn, metadata *C.Metadata) {
|
||||
bufConn, ok := conn.(*CN.BufferedConn)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if sd.force {
|
||||
sd.cover(bufConn, metadata)
|
||||
} else {
|
||||
if metadata.Host != "" {
|
||||
return
|
||||
}
|
||||
|
||||
sd.cover(bufConn, metadata)
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SnifferDispatcher) Enable() bool {
|
||||
return sd.enable
|
||||
}
|
||||
|
||||
func (sd *SnifferDispatcher) cover(conn *CN.BufferedConn, metadata *C.Metadata) {
|
||||
for _, sniffer := range sd.sniffers {
|
||||
if sniffer.SupportNetwork() == C.TCP {
|
||||
conn.Peek(1)
|
||||
len := conn.Buffered()
|
||||
bytes, err := conn.Peek(len)
|
||||
if err != nil {
|
||||
log.Warnln("the data lenght not enough")
|
||||
continue
|
||||
}
|
||||
|
||||
host, err := sniffer.SniffTCP(bytes)
|
||||
if err != nil {
|
||||
log.Warnln("Sniff data failed on Sniffer[%s]", sniffer.Protocol())
|
||||
continue
|
||||
}
|
||||
|
||||
metadata.Host = host
|
||||
metadata.DstIP = nil
|
||||
metadata.AddrType = C.AtypDomainName
|
||||
if resolver.FakeIPEnabled() {
|
||||
metadata.DNSMode = C.DNSFakeIP
|
||||
} else {
|
||||
metadata.DNSMode = C.DNSMapping
|
||||
}
|
||||
|
||||
resolver.InsertHostByIP(metadata.DstIP, host)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewSnifferDispatcher(needSniffer []C.SnifferType, force bool) (SnifferDispatcher, error) {
|
||||
dispatcher := SnifferDispatcher{
|
||||
enable: true,
|
||||
force: force,
|
||||
}
|
||||
|
||||
for _, snifferName := range needSniffer {
|
||||
sniffer, err := NewSniffer(snifferName)
|
||||
if err != nil {
|
||||
log.Errorln("Sniffer name[%s] is error", snifferName)
|
||||
return SnifferDispatcher{enable: false}, err
|
||||
}
|
||||
|
||||
dispatcher.sniffers = append(dispatcher.sniffers, sniffer)
|
||||
}
|
||||
|
||||
return dispatcher, nil
|
||||
}
|
||||
|
||||
func NewSniffer(name C.SnifferType) (C.Sniffer, error) {
|
||||
switch name {
|
||||
case C.TLS:
|
||||
return &TLSSniffer{}, nil
|
||||
default:
|
||||
return nil, ErrorUnsupportedSniffer
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user