From 313493cc9467a599e52cf80957364063d40cbe68 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Wed, 24 Jul 2024 13:59:10 +0800 Subject: [PATCH] chore: add fswatch --- component/process/process.go | 17 +++++++ component/process/process_android.go | 16 ------- component/process/process_common.go | 9 ---- component/process/process_linux.go | 56 +++++++---------------- go.mod | 7 +-- go.sum | 10 +++-- listener/sing_tun/server_android.go | 67 ++++++++++++++++++++++++---- tunnel/tunnel.go | 4 ++ 8 files changed, 106 insertions(+), 80 deletions(-) delete mode 100644 component/process/process_android.go delete mode 100644 component/process/process_common.go diff --git a/component/process/process.go b/component/process/process.go index 76ec2c45..84020c4d 100644 --- a/component/process/process.go +++ b/component/process/process.go @@ -3,6 +3,8 @@ package process import ( "errors" "net/netip" + + C "github.com/metacubex/mihomo/constant" ) var ( @@ -19,3 +21,18 @@ const ( func FindProcessName(network string, srcIP netip.Addr, srcPort int) (uint32, string, error) { return findProcessName(network, srcIP, srcPort) } + +// PackageNameResolver +// never change type traits because it's used in CFMA +type PackageNameResolver func(metadata *C.Metadata) (string, error) + +// DefaultPackageNameResolver +// never change type traits because it's used in CFMA +var DefaultPackageNameResolver PackageNameResolver + +func FindPackageName(metadata *C.Metadata) (string, error) { + if resolver := DefaultPackageNameResolver; resolver != nil { + return resolver(metadata) + } + return "", ErrPlatformNotSupport +} diff --git a/component/process/process_android.go b/component/process/process_android.go deleted file mode 100644 index fd5d3b6c..00000000 --- a/component/process/process_android.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build android && cmfa - -package process - -import "github.com/metacubex/mihomo/constant" - -type PackageNameResolver func(metadata *constant.Metadata) (string, error) - -var DefaultPackageNameResolver PackageNameResolver - -func FindPackageName(metadata *constant.Metadata) (string, error) { - if resolver := DefaultPackageNameResolver; resolver != nil { - return resolver(metadata) - } - return "", ErrPlatformNotSupport -} diff --git a/component/process/process_common.go b/component/process/process_common.go deleted file mode 100644 index fa7eeb9f..00000000 --- a/component/process/process_common.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !(android && cmfa) - -package process - -import "github.com/metacubex/mihomo/constant" - -func FindPackageName(metadata *constant.Metadata) (string, error) { - return "", nil -} diff --git a/component/process/process_linux.go b/component/process/process_linux.go index 45c89e5a..3ce45ae8 100644 --- a/component/process/process_linux.go +++ b/component/process/process_linux.go @@ -2,23 +2,19 @@ package process import ( "bytes" - "context" "encoding/binary" "fmt" "net/netip" "os" + "path" "path/filepath" "runtime" "strings" - "sync" "syscall" "unicode" "unsafe" - "github.com/metacubex/mihomo/log" - "github.com/mdlayher/netlink" - tun "github.com/metacubex/sing-tun" "golang.org/x/sys/unix" ) @@ -63,25 +59,11 @@ type inetDiagResponse struct { INode uint32 } -type MyCallback struct{} - -var ( - packageManager tun.PackageManager - once sync.Once -) - -func (cb *MyCallback) OnPackagesUpdated(packageCount int, sharedCount int) {} - -func (cb *MyCallback) NewError(ctx context.Context, err error) { - log.Warnln("%s", err) -} - func findProcessName(network string, ip netip.Addr, srcPort int) (uint32, string, error) { uid, inode, err := resolveSocketByNetlink(network, ip, srcPort) if err != nil { return 0, "", err } - pp, err := resolveProcessNameByProcSearch(inode, uid) return uid, pp, err } @@ -177,44 +159,38 @@ func resolveProcessNameByProcSearch(inode, uid uint32) (string, error) { if err != nil { continue } + if runtime.GOOS == "android" { if bytes.Equal(buffer[:n], socket) { - return findPackageName(uid), nil + cmdline, err := os.ReadFile(path.Join(processPath, "cmdline")) + if err != nil { + return "", err + } + + return splitCmdline(cmdline), nil } } else { if bytes.Equal(buffer[:n], socket) { return os.Readlink(filepath.Join(processPath, "exe")) } } - } } return "", fmt.Errorf("process of uid(%d),inode(%d) not found", uid, inode) } -func findPackageName(uid uint32) string { - once.Do(func() { - callback := &MyCallback{} - var err error - packageManager, err = tun.NewPackageManager(callback) - if err != nil { - log.Warnln("%s", err) - } - err = packageManager.Start() - if err != nil { - log.Warnln("%s", err) - return - } +func splitCmdline(cmdline []byte) string { + cmdline = bytes.Trim(cmdline, " ") + + idx := bytes.IndexFunc(cmdline, func(r rune) bool { + return unicode.IsControl(r) || unicode.IsSpace(r) }) - if sharedPackage, loaded := packageManager.SharedPackageByID(uid % 100000); loaded { - return sharedPackage + if idx == -1 { + return filepath.Base(string(cmdline)) } - if packageName, loaded := packageManager.PackageByID(uid % 100000); loaded { - return packageName - } - return "" + return filepath.Base(string(cmdline[:idx])) } func isPid(s string) bool { diff --git a/go.mod b/go.mod index ab4125a0..7085d8b1 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72 github.com/metacubex/sing-shadowsocks v0.2.7 github.com/metacubex/sing-shadowsocks2 v0.2.1 - github.com/metacubex/sing-tun v0.2.7-0.20240719141828-5710f5d19a55 + github.com/metacubex/sing-tun v0.2.7-0.20240719141246-19c49ac9589d github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9 github.com/metacubex/sing-wireguard v0.0.0-20240618022557-a6efaa37127a github.com/metacubex/tfo-go v0.0.0-20240228025757-be1269474a66 @@ -36,7 +36,7 @@ require ( github.com/puzpuzpuz/xsync/v3 v3.2.0 github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a - github.com/sagernet/sing v0.5.0-alpha.10 + github.com/sagernet/sing v0.5.0-alpha.13 github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6 github.com/sagernet/sing-shadowtls v0.1.4 github.com/sagernet/wireguard-go v0.0.0-20231209092712-9a439356a62e @@ -93,6 +93,7 @@ require ( github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-20 v0.4.1 // indirect + github.com/sagernet/fswatch v0.1.1 // indirect github.com/sagernet/nftables v0.3.0-beta.4 // indirect github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -112,4 +113,4 @@ require ( golang.org/x/tools v0.22.0 // indirect ) -replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20240617013425-3e3bd9dab6a2 +replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20240724044459-6f3cf5896297 diff --git a/go.sum b/go.sum index 836d9833..ea3b6b53 100644 --- a/go.sum +++ b/go.sum @@ -107,16 +107,16 @@ github.com/metacubex/quic-go v0.45.1-0.20240610004319-163fee60637e h1:bLYn3GuRvW github.com/metacubex/quic-go v0.45.1-0.20240610004319-163fee60637e/go.mod h1:Yza2H7Ax1rxWPUcJx0vW+oAt9EsPuSiyQFhFabUPzwU= github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs= github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY= -github.com/metacubex/sing v0.0.0-20240617013425-3e3bd9dab6a2 h1:N5tidgg/FRmkgPw/AjRwhLUinKDx/ODCSbvv9xqRoLM= -github.com/metacubex/sing v0.0.0-20240617013425-3e3bd9dab6a2/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/metacubex/sing v0.0.0-20240724044459-6f3cf5896297 h1:YG/JkwGPbca5rUtEMHIu8ZuqzR7BSVm1iqY8hNoMeMA= +github.com/metacubex/sing v0.0.0-20240724044459-6f3cf5896297/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72 h1:Wr4g1HCb5Z/QIFwFiVNjO2qL+dRu25+Mdn9xtAZZ+ew= github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72/go.mod h1:g7Mxj7b7zm7YVqD975mk/hSmrb0A0G4bVvIMr2MMzn8= github.com/metacubex/sing-shadowsocks v0.2.7 h1:9f3Dt2+71TNp0e202llA2ug5h/rkWs2EZxQ5IMpf+9g= github.com/metacubex/sing-shadowsocks v0.2.7/go.mod h1:X3x88XtJpBxG0W0/ECOJL6Ib0SJ3xdniAkU/6/RMWU0= github.com/metacubex/sing-shadowsocks2 v0.2.1 h1:XIZBXlazp8EEoPp1S0DViAhLkJakjQ2f+AOwwdKKNYg= github.com/metacubex/sing-shadowsocks2 v0.2.1/go.mod h1:BhOug03a/RbI7y6hp6q+6ITM1dXjnLTmeWBHSTwvv2Q= -github.com/metacubex/sing-tun v0.2.7-0.20240719141828-5710f5d19a55 h1:q7RhLYjTNTmO9aTFCRlKJE3endUHBQNzc7KDFfvTHj8= -github.com/metacubex/sing-tun v0.2.7-0.20240719141828-5710f5d19a55/go.mod h1:WwJGbCx7bQcBzuQXiDOJvZH27R0kIjKNNlISIWsL6kM= +github.com/metacubex/sing-tun v0.2.7-0.20240719141246-19c49ac9589d h1:iYlepjRCYlPXtELupDL+pQjGqkCnQz4KQOfKImP9sog= +github.com/metacubex/sing-tun v0.2.7-0.20240719141246-19c49ac9589d/go.mod h1:olbEx9yVcaw5tHTNlRamRoxmMKcvDvcVS1YLnQGzvWE= github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9 h1:OAXiCosqY8xKDp3pqTW3qbrCprZ1l6WkrXSFSCwyY4I= github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9/go.mod h1:olVkD4FChQ5gKMHG4ZzuD7+fMkJY1G8vwOKpRehjrmY= github.com/metacubex/sing-wireguard v0.0.0-20240618022557-a6efaa37127a h1:NpSGclHJUYndUwBmyIpFBSoBVg8PoVX7QQKhYg0DjM0= @@ -158,6 +158,8 @@ github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58 github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0= github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM= +github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs= +github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o= github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis= github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I= diff --git a/listener/sing_tun/server_android.go b/listener/sing_tun/server_android.go index ac41282d..bd5c4bd0 100644 --- a/listener/sing_tun/server_android.go +++ b/listener/sing_tun/server_android.go @@ -1,29 +1,80 @@ package sing_tun import ( + "errors" + "runtime" + "sync" + + "github.com/metacubex/mihomo/component/process" + "github.com/metacubex/mihomo/constant" + "github.com/metacubex/mihomo/constant/features" "github.com/metacubex/mihomo/log" - tun "github.com/metacubex/sing-tun" + + "github.com/metacubex/sing-tun" "github.com/sagernet/netlink" "golang.org/x/sys/unix" - "runtime" ) -func (l *Listener) buildAndroidRules(tunOptions *tun.Options) error { - packageManager, err := tun.NewPackageManager(l.handler) +type packageManagerCallback struct{} + +func (cb *packageManagerCallback) OnPackagesUpdated(packageCount int, sharedCount int) {} + +func newPackageManager() (tun.PackageManager, error) { + packageManager, err := tun.NewPackageManager(tun.PackageManagerOptions{ + Callback: &packageManagerCallback{}, + Logger: log.SingLogger, + }) if err != nil { - return err + return nil, err } err = packageManager.Start() + if err != nil { + return nil, err + } + return packageManager, nil +} + +var ( + globalPM tun.PackageManager + pmOnce sync.Once + pmErr error +) + +func getPackageManager() (tun.PackageManager, error) { + pmOnce.Do(func() { + globalPM, pmErr = newPackageManager() + }) + return globalPM, pmErr +} + +func (l *Listener) buildAndroidRules(tunOptions *tun.Options) error { + packageManager, err := getPackageManager() if err != nil { return err } - l.packageManager = packageManager tunOptions.BuildAndroidRules(packageManager, l.handler) return nil } -func (h *ListenerHandler) OnPackagesUpdated(packages int, sharedUsers int) { - return +func findPackageName(metadata *constant.Metadata) (string, error) { + packageManager, err := getPackageManager() + if err != nil { + return "", err + } + uid := metadata.Uid + if sharedPackage, loaded := packageManager.SharedPackageByID(uid % 100000); loaded { + return sharedPackage, nil + } + if packageName, loaded := packageManager.PackageByID(uid % 100000); loaded { + return packageName, nil + } + return "", errors.New("package not found") +} + +func init() { + if !features.CMFA { + process.DefaultPackageNameResolver = findPackageName + } } func (l *Listener) openAndroidHotspot(tunOptions tun.Options) { diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 1a6f104d..5dd468f3 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -622,6 +622,10 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) { metadata.Process = filepath.Base(path) metadata.ProcessPath = path metadata.Uid = uid + + if pkg, err := P.FindPackageName(metadata); err == nil { // for android (not CMFA) package names + metadata.Process = pkg + } } } else { // check package names