mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-05-08 14:13:22 +00:00
Routing config: Replace processName with process (full-name/abs-path/abs-folder) (#5496)
About `self/` & `xray/`: https://github.com/XTLS/Xray-core/pull/5496#issuecomment-3714620380 Replaces https://github.com/XTLS/Xray-core/pull/5489
This commit is contained in:
@@ -13,13 +13,13 @@ import (
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
)
|
||||
|
||||
func FindProcess(dest Destination) (int, string, error) {
|
||||
func FindProcess(dest Destination) (PID int, Name string, AbsolutePath string, err error) {
|
||||
isLocal, err := IsLocal(dest.Address.IP())
|
||||
if err != nil {
|
||||
return 0, "", errors.New("failed to determine if address is local: ", err)
|
||||
return 0, "", "", errors.New("failed to determine if address is local: ", err)
|
||||
}
|
||||
if !isLocal {
|
||||
return 0, "", ErrNotLocal
|
||||
return 0, "", "", ErrNotLocal
|
||||
}
|
||||
if dest.Network != Network_TCP && dest.Network != Network_UDP {
|
||||
panic("Unsupported network type for process lookup.")
|
||||
@@ -51,36 +51,39 @@ func FindProcess(dest Destination) (int, string, error) {
|
||||
|
||||
targetHexAddr, err := formatLittleEndianString(dest.Address, dest.Port)
|
||||
if err != nil {
|
||||
return 0, "", errors.New("failed to format address: ", err)
|
||||
return 0, "", "", errors.New("failed to format address: ", err)
|
||||
}
|
||||
|
||||
inode, err := findInodeInFile(procFile, targetHexAddr)
|
||||
if err != nil {
|
||||
return 0, "", errors.New("could not search in ", procFile).Base(err)
|
||||
return 0, "", "", errors.New("could not search in ", procFile).Base(err)
|
||||
}
|
||||
if inode == "" {
|
||||
return 0, "", errors.New("connection for ", dest.Address, ":", dest.Port, " not found in ", procFile)
|
||||
return 0, "", "", errors.New("connection for ", dest.Address, ":", dest.Port, " not found in ", procFile)
|
||||
}
|
||||
|
||||
pidStr, err := findPidByInode(inode)
|
||||
if err != nil {
|
||||
return 0, "", errors.New("could not find PID for inode ", inode, ": ", err)
|
||||
return 0, "", "", errors.New("could not find PID for inode ", inode, ": ", err)
|
||||
}
|
||||
if pidStr == "" {
|
||||
return 0, "", errors.New("no process found for inode ", inode)
|
||||
return 0, "", "", errors.New("no process found for inode ", inode)
|
||||
}
|
||||
|
||||
procName, err := getProcessName(pidStr)
|
||||
absPath, err := getAbsPath(pidStr)
|
||||
if err != nil {
|
||||
return 0, "", fmt.Errorf("could not get process name for PID %s: %w", pidStr, err)
|
||||
return 0, "", "", errors.New("could not get process name for PID ", pidStr, ":", err)
|
||||
}
|
||||
|
||||
nameSplit := strings.Split(absPath, "/")
|
||||
procName := nameSplit[len(nameSplit)-1]
|
||||
|
||||
pid, err := strconv.Atoi(pidStr)
|
||||
if err != nil {
|
||||
return 0, "", errors.New("failed to parse PID: ", err)
|
||||
return 0, "", "", errors.New("failed to parse PID: ", err)
|
||||
}
|
||||
|
||||
return pid, procName, nil
|
||||
return pid, procName, absPath, nil
|
||||
}
|
||||
|
||||
func formatLittleEndianString(addr Address, port Port) (string, error) {
|
||||
@@ -167,12 +170,7 @@ func findPidByInode(inode string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func getProcessName(pid string) (string, error) {
|
||||
path := fmt.Sprintf("/proc/%s/comm", pid)
|
||||
content, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// remove trailing \n
|
||||
return strings.TrimSpace(string(content)), nil
|
||||
func getAbsPath(pid string) (string, error) {
|
||||
path := fmt.Sprintf("/proc/%s/exe", pid)
|
||||
return os.Readlink(path)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ import (
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
)
|
||||
|
||||
func FindProcess(dest Destination) (int, string, error) {
|
||||
return 0, "", errors.New("process lookup is not supported on this platform")
|
||||
func FindProcess(dest Destination) (int, string, string, error) {
|
||||
return 0, "", "", errors.New("process lookup is not supported on this platform")
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ package net
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
@@ -48,19 +49,19 @@ func initWin32API() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindProcess(dest Destination) (int, string, error) {
|
||||
func FindProcess(dest Destination) (PID int, Name string, AbsolutePath string, err error) {
|
||||
once.Do(func() {
|
||||
initErr = initWin32API()
|
||||
})
|
||||
if initErr != nil {
|
||||
return 0, "", initErr
|
||||
return 0, "", "", initErr
|
||||
}
|
||||
isLocal, err := IsLocal(dest.Address.IP())
|
||||
if err != nil {
|
||||
return 0, "", errors.New("failed to determine if address is local: ", err)
|
||||
return 0, "", "", errors.New("failed to determine if address is local: ", err)
|
||||
}
|
||||
if !isLocal {
|
||||
return 0, "", ErrNotLocal
|
||||
return 0, "", "", ErrNotLocal
|
||||
}
|
||||
if dest.Network != Network_TCP && dest.Network != Network_UDP {
|
||||
panic("Unsupported network type for process lookup.")
|
||||
@@ -86,7 +87,7 @@ func FindProcess(dest Destination) (int, string, error) {
|
||||
|
||||
addr, ok := netip.AddrFromSlice(ip)
|
||||
if !ok {
|
||||
return 0, "", errors.New("invalid IP address")
|
||||
return 0, "", "", errors.New("invalid IP address")
|
||||
}
|
||||
addr = addr.Unmap()
|
||||
|
||||
@@ -97,19 +98,23 @@ func FindProcess(dest Destination) (int, string, error) {
|
||||
|
||||
buf, err := getTransportTable(fn, family, class)
|
||||
if err != nil {
|
||||
return 0, "", err
|
||||
return 0, "", "", err
|
||||
}
|
||||
|
||||
s := newSearcher(dest.Network, dest.Address.Family())
|
||||
|
||||
pid, err := s.Search(buf, addr, uint16(port))
|
||||
if err != nil {
|
||||
return 0, "", err
|
||||
return 0, "", "", err
|
||||
}
|
||||
name, err := getExecPathFromPID(pid)
|
||||
// drop .exe
|
||||
name = strings.TrimSuffix(name, ".exe")
|
||||
return int(pid), name, err
|
||||
NameWithPath, err := getExecPathFromPID(pid)
|
||||
NameWithPath = filepath.ToSlash(NameWithPath)
|
||||
|
||||
// drop .exe and path
|
||||
nameSplit := strings.Split(NameWithPath, "/")
|
||||
procName := nameSplit[len(nameSplit)-1]
|
||||
procName = strings.TrimSuffix(procName, ".exe")
|
||||
return int(pid), procName, NameWithPath, err
|
||||
}
|
||||
|
||||
type searcher struct {
|
||||
@@ -234,10 +239,5 @@ func getExecPathFromPID(pid uint32) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// full path will like: C:\Windows\System32\curl.exe
|
||||
// we only need the executable name
|
||||
fullPathName := syscall.UTF16ToString(buf[:size])
|
||||
nameSplit := strings.Split(fullPathName, "\\")
|
||||
name := nameSplit[len(nameSplit)-1]
|
||||
return name, nil
|
||||
return syscall.UTF16ToString(buf[:size]), nil
|
||||
}
|
||||
|
||||
@@ -21,22 +21,22 @@ const ChromeH2KeepAlivePeriod = 45 * time.Second
|
||||
|
||||
var ErrNotLocal = errors.New("the source address is not from local machine.")
|
||||
|
||||
type localIPCahceEntry struct {
|
||||
type localIPCacheEntry struct {
|
||||
addrs []net.Addr
|
||||
lastUpdate time.Time
|
||||
}
|
||||
|
||||
var localIPCahce = atomic.Pointer[localIPCahceEntry]{}
|
||||
var localIPCache = atomic.Pointer[localIPCacheEntry]{}
|
||||
|
||||
func IsLocal(ip net.IP) (bool, error) {
|
||||
var addrs []net.Addr
|
||||
if entry := localIPCahce.Load(); entry == nil || time.Since(entry.lastUpdate) > time.Minute {
|
||||
if entry := localIPCache.Load(); entry == nil || time.Since(entry.lastUpdate) > time.Minute {
|
||||
var err error
|
||||
addrs, err = net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
localIPCahce.Store(&localIPCahceEntry{
|
||||
localIPCache.Store(&localIPCacheEntry{
|
||||
addrs: addrs,
|
||||
lastUpdate: time.Now(),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user