From b4503908df06b6b24a8bf084a8327e96f9fe2e2e Mon Sep 17 00:00:00 2001 From: chain710 Date: Thu, 5 Jan 2023 16:58:36 +0800 Subject: [PATCH] fix #322: add option general.find-process-mode, user can turn off findProcess feature in router findProcess slow down connection due to repeat call to FindProcessName in router environment this option has 3 values: always, strict, off - always, equal to enable-process: true. Just try to merge all process related option into one - strict, as default value, behavior remains unchanged - off, turn off findProcess, useful in router environment --- component/process/find_process_mode.go | 57 +++++++++++ config/config.go | 133 +++++++++++++------------ hub/executor/executor.go | 2 +- tunnel/tunnel.go | 15 ++- 4 files changed, 137 insertions(+), 70 deletions(-) create mode 100644 component/process/find_process_mode.go diff --git a/component/process/find_process_mode.go b/component/process/find_process_mode.go new file mode 100644 index 00000000..06618cef --- /dev/null +++ b/component/process/find_process_mode.go @@ -0,0 +1,57 @@ +package process + +import ( + "encoding/json" + "errors" + "strings" +) + +const ( + FindProcessAlways = "always" + FindProcessStrict = "strict" + FindProcessOff = "off" +) + +var ( + validModes = map[string]struct{}{ + FindProcessAlways: {}, + FindProcessOff: {}, + FindProcessStrict: {}, + } +) + +type FindProcessMode string + +func (m FindProcessMode) Always() bool { + return m == FindProcessAlways +} + +func (m FindProcessMode) Off() bool { + return m == FindProcessOff +} + +func (m *FindProcessMode) UnmarshalYAML(unmarshal func(any) error) error { + var tp string + if err := unmarshal(&tp); err != nil { + return err + } + return m.Set(tp) +} + +func (m *FindProcessMode) UnmarshalJSON(data []byte) error { + var tp string + if err := json.Unmarshal(data, &tp); err != nil { + return err + } + return m.Set(tp) +} + +func (m *FindProcessMode) Set(value string) error { + mode := strings.ToLower(value) + _, exist := validModes[mode] + if !exist { + return errors.New("invalid find process mode") + } + *m = FindProcessMode(mode) + return nil +} diff --git a/config/config.go b/config/config.go index da05877f..e2250e8a 100644 --- a/config/config.go +++ b/config/config.go @@ -4,6 +4,7 @@ import ( "container/list" "errors" "fmt" + P "github.com/Dreamacro/clash/component/process" "net" "net/netip" "net/url" @@ -42,18 +43,19 @@ import ( type General struct { Inbound Controller - Mode T.TunnelMode `json:"mode"` - UnifiedDelay bool - LogLevel log.LogLevel `json:"log-level"` - IPv6 bool `json:"ipv6"` - Interface string `json:"interface-name"` - RoutingMark int `json:"-"` - GeodataMode bool `json:"geodata-mode"` - GeodataLoader string `json:"geodata-loader"` - TCPConcurrent bool `json:"tcp-concurrent"` - EnableProcess bool `json:"enable-process"` - Sniffing bool `json:"sniffing"` - EBpf EBpf `json:"-"` + Mode T.TunnelMode `json:"mode"` + UnifiedDelay bool + LogLevel log.LogLevel `json:"log-level"` + IPv6 bool `json:"ipv6"` + Interface string `json:"interface-name"` + RoutingMark int `json:"-"` + GeodataMode bool `json:"geodata-mode"` + GeodataLoader string `json:"geodata-loader"` + TCPConcurrent bool `json:"tcp-concurrent"` + EnableProcess bool `json:"enable-process"` + FindProcessMode P.FindProcessMode `json:"find-process-mode"` + Sniffing bool `json:"sniffing"` + EBpf EBpf `json:"-"` } // Inbound config @@ -226,32 +228,33 @@ type RawTuicServer struct { } type RawConfig struct { - Port int `yaml:"port"` - SocksPort int `yaml:"socks-port"` - RedirPort int `yaml:"redir-port"` - TProxyPort int `yaml:"tproxy-port"` - MixedPort int `yaml:"mixed-port"` - ShadowSocksConfig string `yaml:"ss-config"` - VmessConfig string `yaml:"vmess-config"` - InboundTfo bool `yaml:"inbound-tfo"` - Authentication []string `yaml:"authentication"` - AllowLan bool `yaml:"allow-lan"` - BindAddress string `yaml:"bind-address"` - Mode T.TunnelMode `yaml:"mode"` - UnifiedDelay bool `yaml:"unified-delay"` - LogLevel log.LogLevel `yaml:"log-level"` - IPv6 bool `yaml:"ipv6"` - ExternalController string `yaml:"external-controller"` - ExternalControllerTLS string `yaml:"external-controller-tls"` - ExternalUI string `yaml:"external-ui"` - Secret string `yaml:"secret"` - Interface string `yaml:"interface-name"` - RoutingMark int `yaml:"routing-mark"` - Tunnels []LC.Tunnel `yaml:"tunnels"` - GeodataMode bool `yaml:"geodata-mode"` - GeodataLoader string `yaml:"geodata-loader"` - TCPConcurrent bool `yaml:"tcp-concurrent" json:"tcp-concurrent"` - EnableProcess bool `yaml:"enable-process" json:"enable-process"` + Port int `yaml:"port"` + SocksPort int `yaml:"socks-port"` + RedirPort int `yaml:"redir-port"` + TProxyPort int `yaml:"tproxy-port"` + MixedPort int `yaml:"mixed-port"` + ShadowSocksConfig string `yaml:"ss-config"` + VmessConfig string `yaml:"vmess-config"` + InboundTfo bool `yaml:"inbound-tfo"` + Authentication []string `yaml:"authentication"` + AllowLan bool `yaml:"allow-lan"` + BindAddress string `yaml:"bind-address"` + Mode T.TunnelMode `yaml:"mode"` + UnifiedDelay bool `yaml:"unified-delay"` + LogLevel log.LogLevel `yaml:"log-level"` + IPv6 bool `yaml:"ipv6"` + ExternalController string `yaml:"external-controller"` + ExternalControllerTLS string `yaml:"external-controller-tls"` + ExternalUI string `yaml:"external-ui"` + Secret string `yaml:"secret"` + Interface string `yaml:"interface-name"` + RoutingMark int `yaml:"routing-mark"` + Tunnels []LC.Tunnel `yaml:"tunnels"` + GeodataMode bool `yaml:"geodata-mode"` + GeodataLoader string `yaml:"geodata-loader"` + TCPConcurrent bool `yaml:"tcp-concurrent" json:"tcp-concurrent"` + EnableProcess bool `yaml:"enable-process" json:"enable-process"` + FindProcessMode P.FindProcessMode `yaml:"find-process-mode" json:"find-process-mode"` Sniffer RawSniffer `yaml:"sniffer"` ProxyProvider map[string]map[string]any `yaml:"proxy-providers"` @@ -314,21 +317,22 @@ func Parse(buf []byte) (*Config, error) { func UnmarshalRawConfig(buf []byte) (*RawConfig, error) { // config with default value rawCfg := &RawConfig{ - AllowLan: false, - BindAddress: "*", - IPv6: true, - Mode: T.Rule, - GeodataMode: C.GeodataMode, - GeodataLoader: "memconservative", - UnifiedDelay: false, - Authentication: []string{}, - LogLevel: log.INFO, - Hosts: map[string]string{}, - Rule: []string{}, - Proxy: []map[string]any{}, - ProxyGroup: []map[string]any{}, - TCPConcurrent: false, - EnableProcess: false, + AllowLan: false, + BindAddress: "*", + IPv6: true, + Mode: T.Rule, + GeodataMode: C.GeodataMode, + GeodataLoader: "memconservative", + UnifiedDelay: false, + Authentication: []string{}, + LogLevel: log.INFO, + Hosts: map[string]string{}, + Rule: []string{}, + Proxy: []map[string]any{}, + ProxyGroup: []map[string]any{}, + TCPConcurrent: false, + EnableProcess: false, + FindProcessMode: P.FindProcessStrict, Tun: RawTun{ Enable: false, Device: "", @@ -536,17 +540,18 @@ func parseGeneral(cfg *RawConfig) (*General, error) { Secret: cfg.Secret, ExternalControllerTLS: cfg.ExternalControllerTLS, }, - UnifiedDelay: cfg.UnifiedDelay, - Mode: cfg.Mode, - LogLevel: cfg.LogLevel, - IPv6: cfg.IPv6, - Interface: cfg.Interface, - RoutingMark: cfg.RoutingMark, - GeodataMode: cfg.GeodataMode, - GeodataLoader: cfg.GeodataLoader, - TCPConcurrent: cfg.TCPConcurrent, - EnableProcess: cfg.EnableProcess, - EBpf: cfg.EBpf, + UnifiedDelay: cfg.UnifiedDelay, + Mode: cfg.Mode, + LogLevel: cfg.LogLevel, + IPv6: cfg.IPv6, + Interface: cfg.Interface, + RoutingMark: cfg.RoutingMark, + GeodataMode: cfg.GeodataMode, + GeodataLoader: cfg.GeodataLoader, + TCPConcurrent: cfg.TCPConcurrent, + EnableProcess: cfg.EnableProcess, + FindProcessMode: cfg.FindProcessMode, + EBpf: cfg.EBpf, }, nil } diff --git a/hub/executor/executor.go b/hub/executor/executor.go index eb4436fb..55786864 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -309,7 +309,7 @@ func updateTunnels(tunnels []LC.Tunnel) { func updateGeneral(general *config.General, force bool) { tunnel.SetMode(general.Mode) - tunnel.SetAlwaysFindProcess(general.EnableProcess) + tunnel.SetFindProcessMode(general.EnableProcess, general.FindProcessMode) dialer.DisableIPv6 = !general.IPv6 if !dialer.DisableIPv6 { log.Infoln("Use IPv6") diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 8f0ef8f6..c5534062 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -43,7 +43,7 @@ var ( // default timeout for UDP session udpTimeout = 60 * time.Second - alwaysFindProcess = false + findProcessMode P.FindProcessMode fakeIPRange netip.Prefix ) @@ -146,9 +146,14 @@ func SetMode(m TunnelMode) { mode = m } -// SetAlwaysFindProcess set always find process info, may be increase many memory -func SetAlwaysFindProcess(findProcess bool) { - alwaysFindProcess = findProcess +// SetFindProcessMode replace SetAlwaysFindProcess +// always find process info if legacyAlways = true or mode.Always() = true, may be increase many memory +func SetFindProcessMode(legacyAlways bool, mode P.FindProcessMode) { + if legacyAlways { + findProcessMode = P.FindProcessAlways + } else { + findProcessMode = mode + } } // processUDP starts a loop to handle udp packet @@ -463,7 +468,7 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) { }() } - if !processFound && (alwaysFindProcess || rule.ShouldFindProcess()) { + if !findProcessMode.Off() && !processFound && (findProcessMode.Always() || rule.ShouldFindProcess()) { srcPort, err := strconv.ParseUint(metadata.SrcPort, 10, 16) uid, path, err := P.FindProcessName(metadata.NetWork.String(), metadata.SrcIP, int(srcPort)) if err != nil {