chore: add force-dns-mapping in sniffer

This commit is contained in:
gVisor bot 2022-10-14 07:46:33 +08:00
parent 5aea89f2fd
commit 02dd19e311
6 changed files with 54 additions and 49 deletions

View file

@ -3,19 +3,18 @@ package sniffer
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/Dreamacro/clash/common/cache"
"github.com/Dreamacro/clash/constant/sniffer"
"net" "net"
"net/netip" "net/netip"
"strconv" "strconv"
"sync" "sync"
"time" "time"
"github.com/Dreamacro/clash/component/trie" "github.com/Dreamacro/clash/common/cache"
N "github.com/Dreamacro/clash/common/net"
CN "github.com/Dreamacro/clash/common/net"
"github.com/Dreamacro/clash/common/utils" "github.com/Dreamacro/clash/common/utils"
"github.com/Dreamacro/clash/component/trie"
C "github.com/Dreamacro/clash/constant" C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/constant/sniffer"
"github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/log"
) )
@ -25,30 +24,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 var Dispatcher *SnifferDispatcher
type ( type SnifferDispatcher struct {
SnifferDispatcher struct {
enable bool enable bool
sniffers []sniffer.Sniffer sniffers []sniffer.Sniffer
foreDomain *trie.DomainTrie[bool] forceDomain *trie.DomainTrie[bool]
skipSNI *trie.DomainTrie[bool] skipSNI *trie.DomainTrie[bool]
portRanges *[]utils.Range[uint16] portRanges *[]utils.Range[uint16]
skipList *cache.LruCache[string, uint8] skipList *cache.LruCache[string, uint8]
rwMux sync.RWMutex rwMux sync.RWMutex
}
) forceDnsMapping bool
}
func (sd *SnifferDispatcher) TCPSniff(conn net.Conn, metadata *C.Metadata) { func (sd *SnifferDispatcher) TCPSniff(conn net.Conn, metadata *C.Metadata) {
bufConn, ok := conn.(*CN.BufferedConn) bufConn, ok := conn.(*N.BufferedConn)
if !ok { if !ok {
return 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) 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")
@ -114,7 +112,7 @@ func (sd *SnifferDispatcher) Enable() bool {
return sd.enable 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 { 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))
@ -177,13 +175,14 @@ func NewCloseSnifferDispatcher() (*SnifferDispatcher, error) {
} }
func NewSnifferDispatcher(needSniffer []sniffer.Type, forceDomain *trie.DomainTrie[bool], 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{ dispatcher := SnifferDispatcher{
enable: true, enable: true,
foreDomain: forceDomain, forceDomain: forceDomain,
skipSNI: skipSNI, skipSNI: skipSNI,
portRanges: ports, portRanges: ports,
skipList: cache.NewLRUCache[string, uint8](cache.WithSize[string, uint8](128), cache.WithAge[string, uint8](600)), skipList: cache.NewLRUCache[string, uint8](cache.WithSize[string, uint8](128), cache.WithAge[string, uint8](600)),
forceDnsMapping: forceDnsMapping,
} }
for _, snifferName := range needSniffer { for _, snifferName := range needSniffer {

View file

@ -4,9 +4,10 @@ import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
C "github.com/Dreamacro/clash/constant"
"net" "net"
"strings" "strings"
C "github.com/Dreamacro/clash/constant"
) )
var ( var (

View file

@ -201,6 +201,7 @@ type Sniffer struct {
ForceDomain *trie.DomainTrie[bool] ForceDomain *trie.DomainTrie[bool]
SkipDomain *trie.DomainTrie[bool] SkipDomain *trie.DomainTrie[bool]
Ports *[]utils.Range[uint16] Ports *[]utils.Range[uint16]
ForceDnsMapping bool
} }
// Experimental config // Experimental config
@ -330,6 +331,7 @@ type RawSniffer struct {
ForceDomain []string `yaml:"force-domain" json:"force-domain"` ForceDomain []string `yaml:"force-domain" json:"force-domain"`
SkipDomain []string `yaml:"skip-domain" json:"skip-domain"` SkipDomain []string `yaml:"skip-domain" json:"skip-domain"`
Ports []string `yaml:"port-whitelist" json:"port-whitelist"` Ports []string `yaml:"port-whitelist" json:"port-whitelist"`
ForceDnsMapping bool `yaml:"force-dns-mapping" json:"force-dns-mapping"`
} }
// EBpf config // EBpf config
@ -424,6 +426,7 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
ForceDomain: []string{}, ForceDomain: []string{},
SkipDomain: []string{}, SkipDomain: []string{},
Ports: []string{}, Ports: []string{},
ForceDnsMapping: true,
}, },
Profile: Profile{ Profile: Profile{
StoreSelected: true, StoreSelected: true,
@ -1174,6 +1177,7 @@ func parseTun(rawTun RawTun, general *General, dnsCfg *DNS) (*Tun, error) {
func parseSniffer(snifferRaw RawSniffer) (*Sniffer, error) { func parseSniffer(snifferRaw RawSniffer) (*Sniffer, error) {
sniffer := &Sniffer{ sniffer := &Sniffer{
Enable: snifferRaw.Enable, Enable: snifferRaw.Enable,
ForceDnsMapping: snifferRaw.ForceDnsMapping,
} }
var ports []utils.Range[uint16] var ports []utils.Range[uint16]

View file

@ -1,10 +1,11 @@
package context package context
import ( import (
CN "github.com/Dreamacro/clash/common/net"
"net" "net"
N "github.com/Dreamacro/clash/common/net"
C "github.com/Dreamacro/clash/constant" C "github.com/Dreamacro/clash/constant"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
) )
@ -20,7 +21,7 @@ func NewConnContext(conn net.Conn, metadata *C.Metadata) *ConnContext {
return &ConnContext{ return &ConnContext{
id: id, id: id,
metadata: metadata, metadata: metadata,
conn: CN.NewBufferedConn(conn), conn: N.NewBufferedConn(conn),
} }
} }

View file

@ -265,7 +265,7 @@ func updateTun(tun *config.Tun) {
func updateSniffer(sniffer *config.Sniffer) { func updateSniffer(sniffer *config.Sniffer) {
if sniffer.Enable { 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 { if err != nil {
log.Warnln("initial sniffer failed, err:%v", err) log.Warnln("initial sniffer failed, err:%v", err)
} }

View file

@ -107,7 +107,7 @@ func UpdateProxies(newProxies map[string]C.Proxy, newProviders map[string]provid
func UpdateSniffer(dispatcher *sniffer.SnifferDispatcher) { func UpdateSniffer(dispatcher *sniffer.SnifferDispatcher) {
configMux.Lock() configMux.Lock()
sniffer.Dispatcher = *dispatcher sniffer.Dispatcher = dispatcher
sniffingEnable = true sniffingEnable = true
configMux.Unlock() configMux.Unlock()
} }