chore: add force-dns-mapping in sniffer
This commit is contained in:
parent
5aea89f2fd
commit
02dd19e311
6 changed files with 54 additions and 49 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
|
@ -195,12 +195,13 @@ type IPTables struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Sniffer struct {
|
type Sniffer struct {
|
||||||
Enable bool
|
Enable bool
|
||||||
Sniffers []sniffer.Type
|
Sniffers []sniffer.Type
|
||||||
Reverses *trie.DomainTrie[bool]
|
Reverses *trie.DomainTrie[bool]
|
||||||
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
|
||||||
|
@ -325,11 +326,12 @@ type RawGeoXUrl struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type RawSniffer struct {
|
type RawSniffer struct {
|
||||||
Enable bool `yaml:"enable" json:"enable"`
|
Enable bool `yaml:"enable" json:"enable"`
|
||||||
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"`
|
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
|
||||||
|
@ -419,11 +421,12 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Sniffer: RawSniffer{
|
Sniffer: RawSniffer{
|
||||||
Enable: false,
|
Enable: false,
|
||||||
Sniffing: []string{},
|
Sniffing: []string{},
|
||||||
ForceDomain: []string{},
|
ForceDomain: []string{},
|
||||||
SkipDomain: []string{},
|
SkipDomain: []string{},
|
||||||
Ports: []string{},
|
Ports: []string{},
|
||||||
|
ForceDnsMapping: true,
|
||||||
},
|
},
|
||||||
Profile: Profile{
|
Profile: Profile{
|
||||||
StoreSelected: true,
|
StoreSelected: true,
|
||||||
|
@ -1173,7 +1176,8 @@ 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]
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue