diff --git a/config/config.go b/config/config.go index d906341..4bd651c 100644 --- a/config/config.go +++ b/config/config.go @@ -86,7 +86,9 @@ type Profile struct { } // Experimental config -type Experimental struct{} +type Experimental struct { + UDPFallbackMatch bool `yaml:"udp-fallback-match"` +} // Config is clash config manager type Config struct { @@ -250,6 +252,9 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) { Profile: Profile{ StoreSelected: true, }, + Experimental: Experimental{ + UDPFallbackMatch: true, + }, } if err := yaml.Unmarshal(buf, rawCfg); err != nil { diff --git a/hub/executor/executor.go b/hub/executor/executor.go index a131f4b..8f94bc7 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -104,7 +104,9 @@ func GetGeneral() *config.General { return general } -func updateExperimental(c *config.Config) {} +func updateExperimental(c *config.Config) { + tunnel.UDPFallbackMatch.Store(c.Experimental.UDPFallbackMatch) +} func updateDNS(c *config.DNS) { if !c.Enable { diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index bf09f23..20e03fd 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -19,6 +19,8 @@ import ( icontext "github.com/Dreamacro/clash/context" "github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/tunnel/statistic" + + "go.uber.org/atomic" ) var ( @@ -35,6 +37,9 @@ var ( // default timeout for UDP session udpTimeout = 60 * time.Second + + // experimental feature + UDPFallbackMatch = atomic.NewBool(false) ) func init() { @@ -407,8 +412,8 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) { continue } - if metadata.NetWork == C.UDP && !adapter.SupportUDP() { - log.Debugln("%s UDP is not supported", adapter.Name()) + if metadata.NetWork == C.UDP && !adapter.SupportUDP() && UDPFallbackMatch.Load() { + log.Debugln("[Matcher] %s UDP is not supported, skip match", adapter.Name()) continue } return adapter, rule, nil