This commit is contained in:
Mazeorz
2021-11-17 16:03:47 +08:00
parent 1f3968bd50
commit 900e852525
115 changed files with 9990 additions and 585 deletions

View File

@ -12,12 +12,14 @@ type TunnelMode int
var ModeMapping = map[string]TunnelMode{
Global.String(): Global,
Rule.String(): Rule,
Script.String(): Script,
Direct.String(): Direct,
}
const (
Global TunnelMode = iota
Rule
Script
Direct
)
@ -61,6 +63,8 @@ func (m TunnelMode) String() string {
return "global"
case Rule:
return "rule"
case Script:
return "script"
case Direct:
return "direct"
default:

View File

@ -77,6 +77,9 @@ func NewTCPTracker(conn C.Conn, manager *Manager, metadata *C.Metadata, rule C.R
if rule != nil {
t.trackerInfo.Rule = rule.RuleType().String()
t.trackerInfo.RulePayload = rule.Payload()
//if rule.RuleType() == C.GEOSITE || rule.RuleType() == C.GEOIP {
// t.trackerInfo.Rule = t.trackerInfo.Rule + " (" + rule.Payload() + ")"
//}
}
manager.Join(t)
@ -134,6 +137,9 @@ func NewUDPTracker(conn C.PacketConn, manager *Manager, metadata *C.Metadata, ru
if rule != nil {
ut.trackerInfo.Rule = rule.RuleType().String()
ut.trackerInfo.RulePayload = rule.Payload()
//if rule.RuleType() == C.GEOSITE || rule.RuleType() == C.GEOIP {
// ut.trackerInfo.Rule = ut.trackerInfo.Rule + " (" + rule.Payload() + ")"
//}
}
manager.Join(ut)

View File

@ -11,10 +11,12 @@ import (
"github.com/Dreamacro/clash/adapter/inbound"
"github.com/Dreamacro/clash/component/nat"
"github.com/Dreamacro/clash/component/resolver"
S "github.com/Dreamacro/clash/component/script"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/constant/provider"
icontext "github.com/Dreamacro/clash/context"
"github.com/Dreamacro/clash/log"
R "github.com/Dreamacro/clash/rule"
"github.com/Dreamacro/clash/tunnel/statistic"
)
@ -32,6 +34,8 @@ var (
// default timeout for UDP session
udpTimeout = 60 * time.Second
preProcessCacheFinder, _ = R.NewProcess("", "", nil)
)
func init() {
@ -141,7 +145,7 @@ func preHandleMetadata(metadata *C.Metadata) error {
// redir-host should lookup the hosts
metadata.DstIP = node.Data.(net.IP)
}
} else if resolver.IsFakeIP(metadata.DstIP) {
} else if resolver.IsFakeIP(metadata.DstIP) && !C.TunBroadcastAddr.Equal(metadata.DstIP) {
return fmt.Errorf("fake DNS record %s missing", metadata.DstIP)
}
}
@ -155,6 +159,8 @@ func resolveMetadata(ctx C.PlainContext, metadata *C.Metadata) (proxy C.Proxy, r
proxy = proxies["DIRECT"]
case Global:
proxy = proxies["GLOBAL"]
case Script:
proxy, err = matchScript(metadata)
// Rule
default:
proxy, rule, err = match(metadata)
@ -235,13 +241,15 @@ func handleUDPConn(packet *inbound.PacketAdapter) {
switch true {
case rule != nil:
log.Infoln("[UDP] %s --> %s match %s(%s) using %s", metadata.SourceAddress(), metadata.RemoteAddress(), rule.RuleType().String(), rule.Payload(), rawPc.Chains().String())
log.Infoln("[UDP] %s(%s) --> %s match %s(%s) using %s", metadata.SourceAddress(), metadata.Process, metadata.RemoteAddress(), rule.RuleType().String(), rule.Payload(), rawPc.Chains().String())
case mode == Script:
log.Infoln("[UDP] %s --> %s using SCRIPT %s", metadata.SourceAddress(), metadata.RemoteAddress(), rawPc.Chains().String())
case mode == Global:
log.Infoln("[UDP] %s --> %s using GLOBAL", metadata.SourceAddress(), metadata.RemoteAddress())
log.Infoln("[UDP] %s(%s) --> %s using GLOBAL", metadata.SourceAddress(), metadata.Process, metadata.RemoteAddress())
case mode == Direct:
log.Infoln("[UDP] %s --> %s using DIRECT", metadata.SourceAddress(), metadata.RemoteAddress())
log.Infoln("[UDP] %s(%s) --> %s using DIRECT", metadata.SourceAddress(), metadata.Process, metadata.RemoteAddress())
default:
log.Infoln("[UDP] %s --> %s doesn't match any rule using DIRECT", metadata.SourceAddress(), metadata.RemoteAddress())
log.Infoln("[UDP] %s(%s) --> %s doesn't match any rule using DIRECT", metadata.SourceAddress(), metadata.Process, metadata.RemoteAddress())
}
go handleUDPToLocal(packet.UDPPacket, pc, key, fAddr)
@ -287,13 +295,15 @@ func handleTCPConn(connCtx C.ConnContext) {
switch true {
case rule != nil:
log.Infoln("[TCP] %s --> %s match %s(%s) using %s", metadata.SourceAddress(), metadata.RemoteAddress(), rule.RuleType().String(), rule.Payload(), remoteConn.Chains().String())
log.Infoln("[TCP] %s(%s) --> %s match %s(%s) using %s", metadata.SourceAddress(), metadata.Process, metadata.RemoteAddress(), rule.RuleType().String(), rule.Payload(), remoteConn.Chains().String())
case mode == Script:
log.Infoln("[TCP] %s(%s) --> %s using SCRIPT %s", metadata.SourceAddress(), metadata.Process, metadata.RemoteAddress(), remoteConn.Chains().String())
case mode == Global:
log.Infoln("[TCP] %s --> %s using GLOBAL", metadata.SourceAddress(), metadata.RemoteAddress())
log.Infoln("[TCP] %s(%s) --> %s using GLOBAL", metadata.SourceAddress(), metadata.Process, metadata.RemoteAddress())
case mode == Direct:
log.Infoln("[TCP] %s --> %s using DIRECT", metadata.SourceAddress(), metadata.RemoteAddress())
log.Infoln("[TCP] %s(%s) --> %s using DIRECT", metadata.SourceAddress(), metadata.Process, metadata.RemoteAddress())
default:
log.Infoln("[TCP] %s --> %s doesn't match any rule using DIRECT", metadata.SourceAddress(), metadata.RemoteAddress())
log.Infoln("[TCP] %s(%s) --> %s doesn't match any rule using DIRECT", metadata.SourceAddress(), metadata.Process, metadata.RemoteAddress())
}
handleSocket(connCtx, remoteConn)
@ -315,6 +325,9 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) {
resolved = true
}
// preset process name and cache it
preProcessCacheFinder.Match(metadata)
for _, rule := range rules {
if !resolved && shouldResolveIP(rule, metadata) {
ip, err := resolver.ResolveIP(metadata.Host)
@ -337,9 +350,45 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) {
log.Debugln("%s UDP is not supported", adapter.Name())
continue
}
extra := rule.RuleExtra()
if extra != nil {
if extra.NotMatchNetwork(metadata.NetWork) {
continue
}
if extra.NotMatchSourceIP(metadata.SrcIP) {
continue
}
}
return adapter, rule, nil
}
}
return proxies["DIRECT"], nil, nil
return proxies["REJECT"], nil, nil
}
func matchScript(metadata *C.Metadata) (C.Proxy, error) {
configMux.RLock()
defer configMux.RUnlock()
if node := resolver.DefaultHosts.Search(metadata.Host); node != nil {
ip := node.Data.(net.IP)
metadata.DstIP = ip
}
// preset process name and cache it
preProcessCacheFinder.Match(metadata)
adapter, err := S.CallPyMainFunction(metadata)
if err != nil {
return nil, err
}
if _, ok := proxies[adapter]; !ok {
return nil, fmt.Errorf("proxy [%s] not found by script", adapter)
}
return proxies[adapter], nil
}