diff --git a/app/router/condition.go b/app/router/condition.go index 54af8165..a9889a6e 100644 --- a/app/router/condition.go +++ b/app/router/condition.go @@ -390,8 +390,10 @@ func (m *ProcessNameMatcher) Apply(ctx routing.Context) bool { if len(ctx.GetSourceIPs()) == 0 { return false } - srcPort := ctx.GetSourcePort().String() + + srcPort := uint16(ctx.GetSourcePort()) srcIP := ctx.GetSourceIPs()[0].String() + var network string switch ctx.GetNetwork() { case net.Network_TCP: @@ -401,11 +403,15 @@ func (m *ProcessNameMatcher) Apply(ctx routing.Context) bool { default: return false } - src, err := net.ParseDestination(strings.Join([]string{network, srcIP, srcPort}, ":")) - if err != nil { - return false + + var dstIP string + var dstPort uint16 = 0 + if len(ctx.GetTargetIPs()) > 0 { + dstIP = ctx.GetTargetIPs()[0].String() + dstPort = uint16(ctx.GetTargetPort()) } - pid, name, absPath, err := net.FindProcess(src) + + pid, name, absPath, err := net.FindProcess(network, srcIP, uint16(srcPort), dstIP, uint16(dstPort)) if err != nil { if err != net.ErrNotLocal { errors.LogError(context.Background(), "Unables to find local process name: ", err) diff --git a/common/net/find_process_android.go b/common/net/find_process_android.go new file mode 100644 index 00000000..5d9ecce0 --- /dev/null +++ b/common/net/find_process_android.go @@ -0,0 +1,20 @@ +//go:build android + +package net + +import ( + "github.com/xtls/xray-core/common/errors" +) + +var androidProcessFinder func(network, srcIP string, srcPort uint16, destIP string, destPort uint16) (int, string, string, error) + +func RegisterAndroidProcessFinder(f func(network, srcIP string, srcPort uint16, destIP string, destPort uint16) (int, string, string, error)) { + androidProcessFinder = f +} + +func FindProcess(network, srcIP string, srcPort uint16, destIP string, destPort uint16) (int, string, string, error) { + if androidProcessFinder != nil { + return androidProcessFinder(network, srcIP, srcPort, destIP, destPort) + } + return 0, "", "", errors.New("android process lookup must be registered before use") +} diff --git a/common/net/find_process_linux.go b/common/net/find_process_linux.go index 95e03935..2e661a4d 100644 --- a/common/net/find_process_linux.go +++ b/common/net/find_process_linux.go @@ -1,4 +1,4 @@ -//go:build linux +//go:build linux && !android package net @@ -6,6 +6,7 @@ import ( "bufio" "encoding/hex" "fmt" + "net" "os" "strconv" "strings" @@ -13,43 +14,38 @@ import ( "github.com/xtls/xray-core/common/errors" ) -func FindProcess(dest Destination) (PID int, Name string, AbsolutePath string, err error) { - isLocal, err := IsLocal(dest.Address.IP()) +func FindProcess(network, srcIP string, srcPort uint16, destIP string, destPort uint16) (PID int, Name string, AbsolutePath string, err error) { + isLocal, err := IsLocal(net.ParseIP(srcIP)) if err != nil { return 0, "", "", errors.New("failed to determine if address is local: ", err) } if !isLocal { return 0, "", "", ErrNotLocal } - if dest.Network != Network_TCP && dest.Network != Network_UDP { + if network != "tcp" && network != "udp" { panic("Unsupported network type for process lookup.") } - // the core should never has a domain as source(? - if dest.Address.Family() == AddressFamilyDomain { - panic("Domain addresses are not supported for process lookup.") - } + var procFile string - switch dest.Network { - case Network_TCP: - if dest.Address.Family() == AddressFamilyIPv4 { + switch network { + case "tcp": + if net.ParseIP(srcIP).To4() != nil { procFile = "/proc/net/tcp" - } - if dest.Address.Family() == AddressFamilyIPv6 { + } else { procFile = "/proc/net/tcp6" } - case Network_UDP: - if dest.Address.Family() == AddressFamilyIPv4 { + case "udp": + if net.ParseIP(srcIP).To4() != nil { procFile = "/proc/net/udp" - } - if dest.Address.Family() == AddressFamilyIPv6 { + } else { procFile = "/proc/net/udp6" } default: panic("Unsupported network type for process lookup.") } - targetHexAddr, err := formatLittleEndianString(dest.Address, dest.Port) + targetHexAddr, err := formatLittleEndianString(net.ParseIP(srcIP), Port(srcPort)) if err != nil { return 0, "", "", errors.New("failed to format address: ", err) } @@ -59,7 +55,7 @@ func FindProcess(dest Destination) (PID int, Name string, AbsolutePath string, e 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 ", srcIP, ":", srcPort, " not found in ", procFile) } pidStr, err := findPidByInode(inode) @@ -86,16 +82,16 @@ func FindProcess(dest Destination) (PID int, Name string, AbsolutePath string, e return pid, procName, absPath, nil } -func formatLittleEndianString(addr Address, port Port) (string, error) { - ip := addr.IP() +func formatLittleEndianString(addr net.IP, port Port) (string, error) { + ip := addr var ipBytes []byte - if addr.Family() == AddressFamilyIPv4 { + if ip.To4() != nil { ipBytes = ip.To4() } else { ipBytes = ip.To16() } if ipBytes == nil { - return "", errors.New("invalid IP format for ", addr.Family(), ": ", ip) + return "", errors.New("invalid IP format for ", addr, ": ", ip) } for i, j := 0, len(ipBytes)-1; i < j; i, j = i+1, j-1 { diff --git a/common/net/find_process_others.go b/common/net/find_process_others.go index a47b5b93..22e42bdc 100644 --- a/common/net/find_process_others.go +++ b/common/net/find_process_others.go @@ -1,4 +1,4 @@ -//go:build !windows && !linux +//go:build !windows && !linux && !android package net @@ -6,6 +6,6 @@ import ( "github.com/xtls/xray-core/common/errors" ) -func FindProcess(dest Destination) (int, string, string, error) { +func FindProcess(network, srcIP string, srcPort uint16, destIP string, destPort uint16) (int, string, string, error) { return 0, "", "", errors.New("process lookup is not supported on this platform") } diff --git a/common/net/find_process_windows.go b/common/net/find_process_windows.go index 46ddcc9c..95420255 100644 --- a/common/net/find_process_windows.go +++ b/common/net/find_process_windows.go @@ -3,6 +3,7 @@ package net import ( + "net" "net/netip" "path/filepath" "strings" @@ -49,41 +50,37 @@ func initWin32API() error { return nil } -func FindProcess(dest Destination) (PID int, Name string, AbsolutePath string, err error) { +func FindProcess(network, srcIP string, srcPort uint16, destIP string, destPort uint16) (PID int, Name string, AbsolutePath string, err error) { once.Do(func() { initErr = initWin32API() }) if initErr != nil { return 0, "", "", initErr } - isLocal, err := IsLocal(dest.Address.IP()) + isLocal, err := IsLocal(net.ParseIP(srcIP)) if err != nil { return 0, "", "", errors.New("failed to determine if address is local: ", err) } if !isLocal { return 0, "", "", ErrNotLocal } - if dest.Network != Network_TCP && dest.Network != Network_UDP { + if network != "tcp" && network != "udp" { panic("Unsupported network type for process lookup.") } - // the core should never has a domain as source(? - if dest.Address.Family() == AddressFamilyDomain { - panic("Domain addresses are not supported for process lookup.") - } var class int var fn uintptr - switch dest.Network { - case Network_TCP: + switch network { + case "tcp": fn = getExTCPTable class = tcpTablePidConn - case Network_UDP: + case "udp": fn = getExUDPTable class = udpTablePid default: panic("Unsupported network type for process lookup.") } - ip := dest.Address.IP() - port := int(dest.Port) + ip := net.ParseIP(srcIP) + port := int(srcPort) addr, ok := netip.AddrFromSlice(ip) if !ok { @@ -101,7 +98,15 @@ func FindProcess(dest Destination) (PID int, Name string, AbsolutePath string, e return 0, "", "", err } - s := newSearcher(dest.Network, dest.Address.Family()) + networkType := Network_TCP + if network == "udp" { + networkType = Network_UDP + } + familyType := AddressFamilyIPv4 + if addr.Is6() { + familyType = AddressFamilyIPv6 + } + s := newSearcher(networkType, familyType) pid, err := s.Search(buf, addr, uint16(port)) if err != nil {