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
This commit is contained in:
chain710 2023-01-05 16:58:36 +08:00 committed by metacubex
parent fd48c6df8a
commit b4503908df
4 changed files with 137 additions and 70 deletions

View file

@ -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
}

View file

@ -4,6 +4,7 @@ import (
"container/list"
"errors"
"fmt"
P "github.com/Dreamacro/clash/component/process"
"net"
"net/netip"
"net/url"
@ -52,6 +53,7 @@ type General struct {
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:"-"`
}
@ -252,6 +254,7 @@ type RawConfig struct {
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"`
@ -329,6 +332,7 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
ProxyGroup: []map[string]any{},
TCPConcurrent: false,
EnableProcess: false,
FindProcessMode: P.FindProcessStrict,
Tun: RawTun{
Enable: false,
Device: "",
@ -546,6 +550,7 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
GeodataLoader: cfg.GeodataLoader,
TCPConcurrent: cfg.TCPConcurrent,
EnableProcess: cfg.EnableProcess,
FindProcessMode: cfg.FindProcessMode,
EBpf: cfg.EBpf,
}, nil
}

View file

@ -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")

View file

@ -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 {