mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2024-11-16 11:42:43 +08:00
feat: add override-destination for sniffer
This commit is contained in:
parent
df1f6e2b99
commit
096bb8d439
|
@ -9,7 +9,8 @@ import (
|
|||
)
|
||||
|
||||
type SnifferConfig struct {
|
||||
Ports []utils.Range[uint16]
|
||||
OverrideDest bool
|
||||
Ports []utils.Range[uint16]
|
||||
}
|
||||
|
||||
type BaseSniffer struct {
|
||||
|
|
|
@ -26,15 +26,12 @@ var (
|
|||
var Dispatcher *SnifferDispatcher
|
||||
|
||||
type SnifferDispatcher struct {
|
||||
enable bool
|
||||
|
||||
sniffers []sniffer.Sniffer
|
||||
|
||||
forceDomain *trie.DomainTrie[struct{}]
|
||||
skipSNI *trie.DomainTrie[struct{}]
|
||||
skipList *cache.LruCache[string, uint8]
|
||||
rwMux sync.RWMutex
|
||||
|
||||
enable bool
|
||||
sniffers map[sniffer.Sniffer]SnifferConfig
|
||||
forceDomain *trie.DomainTrie[struct{}]
|
||||
skipSNI *trie.DomainTrie[struct{}]
|
||||
skipList *cache.LruCache[string, uint8]
|
||||
rwMux sync.RWMutex
|
||||
forceDnsMapping bool
|
||||
parsePureIp bool
|
||||
}
|
||||
|
@ -53,10 +50,12 @@ func (sd *SnifferDispatcher) TCPSniff(conn net.Conn, metadata *C.Metadata) {
|
|||
}
|
||||
|
||||
inWhitelist := false
|
||||
for _, sniffer := range sd.sniffers {
|
||||
overrideDest := false
|
||||
for sniffer, config := range sd.sniffers {
|
||||
if sniffer.SupportNetwork() == C.TCP || sniffer.SupportNetwork() == C.ALLNet {
|
||||
inWhitelist = sniffer.SupportPort(uint16(port))
|
||||
if inWhitelist {
|
||||
overrideDest = config.OverrideDest
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -89,12 +88,12 @@ func (sd *SnifferDispatcher) TCPSniff(conn net.Conn, metadata *C.Metadata) {
|
|||
sd.skipList.Delete(dst)
|
||||
sd.rwMux.RUnlock()
|
||||
|
||||
sd.replaceDomain(metadata, host)
|
||||
sd.replaceDomain(metadata, host, overrideDest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SnifferDispatcher) replaceDomain(metadata *C.Metadata, host string) {
|
||||
func (sd *SnifferDispatcher) replaceDomain(metadata *C.Metadata, host string, overrideDest bool) {
|
||||
dstIP := ""
|
||||
if metadata.DstIP.IsValid() {
|
||||
dstIP = metadata.DstIP.String()
|
||||
|
@ -112,7 +111,11 @@ func (sd *SnifferDispatcher) replaceDomain(metadata *C.Metadata, host string) {
|
|||
metadata.Host, host)
|
||||
}
|
||||
|
||||
metadata.Host = host
|
||||
if overrideDest {
|
||||
metadata.Host = host
|
||||
} else {
|
||||
metadata.SniffHost = host
|
||||
}
|
||||
metadata.DNSMode = C.DNSNormal
|
||||
}
|
||||
|
||||
|
@ -121,7 +124,7 @@ func (sd *SnifferDispatcher) Enable() bool {
|
|||
}
|
||||
|
||||
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 {
|
||||
_ = conn.SetReadDeadline(time.Now().Add(1 * time.Second))
|
||||
_, err := conn.Peek(1)
|
||||
|
@ -189,9 +192,10 @@ func NewSnifferDispatcher(snifferConfig map[sniffer.Type]SnifferConfig, forceDom
|
|||
enable: true,
|
||||
forceDomain: forceDomain,
|
||||
skipSNI: skipSNI,
|
||||
skipList: cache.New[string, uint8](cache.WithSize[string, uint8](128), cache.WithAge[string, uint8](600)),
|
||||
skipList: cache.New(cache.WithSize[string, uint8](128), cache.WithAge[string, uint8](600)),
|
||||
forceDnsMapping: forceDnsMapping,
|
||||
parsePureIp: parsePureIp,
|
||||
sniffers: make(map[sniffer.Sniffer]SnifferConfig, 0),
|
||||
}
|
||||
|
||||
for snifferName, config := range snifferConfig {
|
||||
|
@ -200,8 +204,7 @@ func NewSnifferDispatcher(snifferConfig map[sniffer.Type]SnifferConfig, forceDom
|
|||
log.Errorln("Sniffer name[%s] is error", snifferName)
|
||||
return &SnifferDispatcher{enable: false}, err
|
||||
}
|
||||
|
||||
dispatcher.sniffers = append(dispatcher.sniffers, s)
|
||||
dispatcher.sniffers[s] = config
|
||||
}
|
||||
|
||||
return &dispatcher, nil
|
||||
|
|
|
@ -288,6 +288,7 @@ type RawGeoXUrl struct {
|
|||
|
||||
type RawSniffer struct {
|
||||
Enable bool `yaml:"enable" json:"enable"`
|
||||
OverrideDest bool `yaml:"override-destination" json:"override-destination"`
|
||||
Sniffing []string `yaml:"sniffing" json:"sniffing"`
|
||||
ForceDomain []string `yaml:"force-domain" json:"force-domain"`
|
||||
SkipDomain []string `yaml:"skip-domain" json:"skip-domain"`
|
||||
|
@ -298,7 +299,8 @@ type RawSniffer struct {
|
|||
}
|
||||
|
||||
type RawSniffingConfig struct {
|
||||
Ports []string `yaml:"ports" json:"ports"`
|
||||
Ports []string `yaml:"ports" json:"ports"`
|
||||
OverrideDest *bool `yaml:"override-destination" json:"override-destination"`
|
||||
}
|
||||
|
||||
// EBpf config
|
||||
|
@ -1201,11 +1203,16 @@ func parseSniffer(snifferRaw RawSniffer) (*Sniffer, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
overrideDest := snifferRaw.OverrideDest
|
||||
if sniffConfig.OverrideDest != nil {
|
||||
overrideDest = *sniffConfig.OverrideDest
|
||||
}
|
||||
for _, snifferType := range snifferTypes.List {
|
||||
if snifferType.String() == strings.ToUpper(sniffType) {
|
||||
find = true
|
||||
loadSniffer[snifferType] = SNIFF.SnifferConfig{
|
||||
Ports: ports,
|
||||
Ports: ports,
|
||||
OverrideDest: overrideDest,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1228,7 +1235,8 @@ func parseSniffer(snifferRaw RawSniffer) (*Sniffer, error) {
|
|||
if snifferType.String() == strings.ToUpper(snifferName) {
|
||||
find = true
|
||||
loadSniffer[snifferType] = SNIFF.SnifferConfig{
|
||||
Ports: globalPorts,
|
||||
Ports: globalPorts,
|
||||
OverrideDest: snifferRaw.OverrideDest,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,6 +134,8 @@ type Metadata struct {
|
|||
SpecialProxy string `json:"specialProxy"`
|
||||
SpecialRules string `json:"specialRules"`
|
||||
RemoteDst string `json:"remoteDestination"`
|
||||
// Only domain rule
|
||||
SniffHost string
|
||||
}
|
||||
|
||||
func (m *Metadata) RemoteAddress() string {
|
||||
|
@ -176,6 +178,14 @@ func (m *Metadata) Resolved() bool {
|
|||
return m.DstIP.IsValid()
|
||||
}
|
||||
|
||||
func (m *Metadata) RuleHost() string {
|
||||
if len(m.SniffHost) == 0 {
|
||||
return m.Host
|
||||
} else {
|
||||
return m.SniffHost
|
||||
}
|
||||
}
|
||||
|
||||
// Pure is used to solve unexpected behavior
|
||||
// when dialing proxy connection in DNSMapping mode.
|
||||
func (m *Metadata) Pure() *Metadata {
|
||||
|
|
|
@ -19,7 +19,7 @@ func (d *Domain) RuleType() C.RuleType {
|
|||
}
|
||||
|
||||
func (d *Domain) Match(metadata *C.Metadata) (bool, string) {
|
||||
return metadata.Host == d.domain, d.adapter
|
||||
return metadata.RuleHost() == d.domain, d.adapter
|
||||
}
|
||||
|
||||
func (d *Domain) Adapter() string {
|
||||
|
|
|
@ -19,7 +19,7 @@ func (dk *DomainKeyword) RuleType() C.RuleType {
|
|||
}
|
||||
|
||||
func (dk *DomainKeyword) Match(metadata *C.Metadata) (bool, string) {
|
||||
domain := metadata.Host
|
||||
domain := metadata.RuleHost()
|
||||
return strings.Contains(domain, dk.keyword), dk.adapter
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ func (ds *DomainSuffix) RuleType() C.RuleType {
|
|||
}
|
||||
|
||||
func (ds *DomainSuffix) Match(metadata *C.Metadata) (bool, string) {
|
||||
domain := metadata.Host
|
||||
domain := metadata.RuleHost()
|
||||
return strings.HasSuffix(domain, "."+ds.suffix) || domain == ds.suffix, ds.adapter
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ func (gs *GEOSITE) Match(metadata *C.Metadata) (bool, string) {
|
|||
return false, ""
|
||||
}
|
||||
|
||||
domain := metadata.Host
|
||||
domain := metadata.RuleHost()
|
||||
return gs.matcher.ApplyDomain(domain), gs.adapter
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ func (d *domainStrategy) ShouldFindProcess() bool {
|
|||
}
|
||||
|
||||
func (d *domainStrategy) Match(metadata *C.Metadata) bool {
|
||||
return d.domainRules != nil && d.domainRules.Search(metadata.Host) != nil
|
||||
return d.domainRules != nil && d.domainRules.Search(metadata.RuleHost()) != nil
|
||||
}
|
||||
|
||||
func (d *domainStrategy) Count() int {
|
||||
|
|
Loading…
Reference in New Issue
Block a user