feat: 安卓恢复进程规则,可通过enable-process开关,默认true
This commit is contained in:
parent
db2bf61714
commit
2a00f57fd9
11 changed files with 280 additions and 29 deletions
|
@ -6,13 +6,14 @@ import (
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"runtime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrInvalidNetwork = errors.New("invalid network")
|
ErrInvalidNetwork = errors.New("invalid network")
|
||||||
ErrPlatformNotSupport = errors.New("not support on this platform")
|
ErrPlatformNotSupport = errors.New("not support on this platform")
|
||||||
ErrNotFound = errors.New("process not found")
|
ErrNotFound = errors.New("process not found")
|
||||||
|
|
||||||
|
enableFindProcess = true
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -20,7 +21,11 @@ const (
|
||||||
UDP = "udp"
|
UDP = "udp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func FindProcessName(network string, srcIP netip.Addr, srcPort int) (string, error) {
|
func EnableFindProcess(e bool) {
|
||||||
|
enableFindProcess = e
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindProcessName(network string, srcIP netip.Addr, srcPort int) (int32, string, error) {
|
||||||
return findProcessName(network, srcIP, srcPort)
|
return findProcessName(network, srcIP, srcPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,10 +38,7 @@ func FindUid(network string, srcIP netip.Addr, srcPort int) (int32, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ShouldFindProcess(metadata *C.Metadata) bool {
|
func ShouldFindProcess(metadata *C.Metadata) bool {
|
||||||
if runtime.GOOS == "android" {
|
if !enableFindProcess || metadata.Process != "" || metadata.ProcessPath != "" {
|
||||||
return false
|
|
||||||
}
|
|
||||||
if metadata.Process != "" || metadata.ProcessPath != "" {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, ip := range localIPs {
|
for _, ip := range localIPs {
|
||||||
|
|
228
component/process/process_android.go
Normal file
228
component/process/process_android.go
Normal file
|
@ -0,0 +1,228 @@
|
||||||
|
package process
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"unicode"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/common/pool"
|
||||||
|
)
|
||||||
|
|
||||||
|
// from https://github.com/vishvananda/netlink/blob/bca67dfc8220b44ef582c9da4e9172bf1c9ec973/nl/nl_linux.go#L52-L62
|
||||||
|
var nativeEndian = func() binary.ByteOrder {
|
||||||
|
var x uint32 = 0x01020304
|
||||||
|
if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
|
||||||
|
return binary.BigEndian
|
||||||
|
}
|
||||||
|
|
||||||
|
return binary.LittleEndian
|
||||||
|
}()
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeOfSocketDiagRequest = syscall.SizeofNlMsghdr + 8 + 48
|
||||||
|
socketDiagByFamily = 20
|
||||||
|
pathProc = "/proc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func findProcessName(network string, ip netip.Addr, srcPort int) (int32, string, error) {
|
||||||
|
inode, uid, err := resolveSocketByNetlink(network, ip, srcPort)
|
||||||
|
if err != nil {
|
||||||
|
return -1, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
pp, err := resolveProcessNameByProcSearch(inode, uid)
|
||||||
|
return uid, pp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (int32, int32, error) {
|
||||||
|
var family byte
|
||||||
|
var protocol byte
|
||||||
|
|
||||||
|
switch network {
|
||||||
|
case TCP:
|
||||||
|
protocol = syscall.IPPROTO_TCP
|
||||||
|
case UDP:
|
||||||
|
protocol = syscall.IPPROTO_UDP
|
||||||
|
default:
|
||||||
|
return 0, 0, ErrInvalidNetwork
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip.Is4() {
|
||||||
|
family = syscall.AF_INET
|
||||||
|
} else {
|
||||||
|
family = syscall.AF_INET6
|
||||||
|
}
|
||||||
|
|
||||||
|
req := packSocketDiagRequest(family, protocol, ip, uint16(srcPort))
|
||||||
|
|
||||||
|
socket, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_DGRAM, syscall.NETLINK_INET_DIAG)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, fmt.Errorf("dial netlink: %w", err)
|
||||||
|
}
|
||||||
|
defer syscall.Close(socket)
|
||||||
|
|
||||||
|
_ = syscall.SetsockoptTimeval(socket, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &syscall.Timeval{Usec: 100})
|
||||||
|
_ = syscall.SetsockoptTimeval(socket, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &syscall.Timeval{Usec: 100})
|
||||||
|
|
||||||
|
if err := syscall.Connect(socket, &syscall.SockaddrNetlink{
|
||||||
|
Family: syscall.AF_NETLINK,
|
||||||
|
Pad: 0,
|
||||||
|
Pid: 0,
|
||||||
|
Groups: 0,
|
||||||
|
}); err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := syscall.Write(socket, req); err != nil {
|
||||||
|
return 0, 0, fmt.Errorf("write request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rb := pool.Get(pool.RelayBufferSize)
|
||||||
|
defer pool.Put(rb)
|
||||||
|
|
||||||
|
n, err := syscall.Read(socket, rb)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, fmt.Errorf("read response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
messages, err := syscall.ParseNetlinkMessage(rb[:n])
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, fmt.Errorf("parse netlink message: %w", err)
|
||||||
|
} else if len(messages) == 0 {
|
||||||
|
return 0, 0, fmt.Errorf("unexcepted netlink response")
|
||||||
|
}
|
||||||
|
|
||||||
|
message := messages[0]
|
||||||
|
if message.Header.Type&syscall.NLMSG_ERROR != 0 {
|
||||||
|
return 0, 0, fmt.Errorf("netlink message: NLMSG_ERROR")
|
||||||
|
}
|
||||||
|
|
||||||
|
uid, inode := unpackSocketDiagResponse(&messages[0])
|
||||||
|
if uid < 0 || inode < 0 {
|
||||||
|
return 0, 0, fmt.Errorf("invalid uid(%d) or inode(%d)", uid, inode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return uid, inode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func packSocketDiagRequest(family, protocol byte, source netip.Addr, sourcePort uint16) []byte {
|
||||||
|
s := make([]byte, 16)
|
||||||
|
|
||||||
|
copy(s, source.AsSlice())
|
||||||
|
|
||||||
|
buf := make([]byte, sizeOfSocketDiagRequest)
|
||||||
|
|
||||||
|
nativeEndian.PutUint32(buf[0:4], sizeOfSocketDiagRequest)
|
||||||
|
nativeEndian.PutUint16(buf[4:6], socketDiagByFamily)
|
||||||
|
nativeEndian.PutUint16(buf[6:8], syscall.NLM_F_REQUEST|syscall.NLM_F_DUMP)
|
||||||
|
nativeEndian.PutUint32(buf[8:12], 0)
|
||||||
|
nativeEndian.PutUint32(buf[12:16], 0)
|
||||||
|
|
||||||
|
buf[16] = family
|
||||||
|
buf[17] = protocol
|
||||||
|
buf[18] = 0
|
||||||
|
buf[19] = 0
|
||||||
|
nativeEndian.PutUint32(buf[20:24], 0xFFFFFFFF)
|
||||||
|
|
||||||
|
binary.BigEndian.PutUint16(buf[24:26], sourcePort)
|
||||||
|
binary.BigEndian.PutUint16(buf[26:28], 0)
|
||||||
|
|
||||||
|
copy(buf[28:44], s)
|
||||||
|
copy(buf[44:60], net.IPv6zero)
|
||||||
|
|
||||||
|
nativeEndian.PutUint32(buf[60:64], 0)
|
||||||
|
nativeEndian.PutUint64(buf[64:72], 0xFFFFFFFFFFFFFFFF)
|
||||||
|
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
func unpackSocketDiagResponse(msg *syscall.NetlinkMessage) (inode, uid int32) {
|
||||||
|
if len(msg.Data) < 72 {
|
||||||
|
return 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
data := msg.Data
|
||||||
|
|
||||||
|
uid = int32(nativeEndian.Uint32(data[64:68]))
|
||||||
|
inode = int32(nativeEndian.Uint32(data[68:72]))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveProcessNameByProcSearch(inode, uid int32) (string, error) {
|
||||||
|
files, err := os.ReadDir(pathProc)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := make([]byte, syscall.PathMax)
|
||||||
|
socket := []byte(fmt.Sprintf("socket:[%d]", inode))
|
||||||
|
|
||||||
|
for _, f := range files {
|
||||||
|
if !f.IsDir() || !isPid(f.Name()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := f.Info()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if info.Sys().(*syscall.Stat_t).Uid != uint32(uid) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
processPath := path.Join(pathProc, f.Name())
|
||||||
|
fdPath := path.Join(processPath, "fd")
|
||||||
|
|
||||||
|
fds, err := os.ReadDir(fdPath)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, fd := range fds {
|
||||||
|
n, err := syscall.Readlink(path.Join(fdPath, fd.Name()), buffer)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytes.Equal(buffer[:n], socket) {
|
||||||
|
cmdline, err := os.ReadFile(path.Join(processPath, "cmdline"))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return splitCmdline(cmdline), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("process of uid(%d),inode(%d) not found", uid, inode)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 idx == -1 {
|
||||||
|
return filepath.Base(string(cmdline))
|
||||||
|
}
|
||||||
|
return filepath.Base(string(cmdline[:idx]))
|
||||||
|
}
|
||||||
|
|
||||||
|
func isPid(s string) bool {
|
||||||
|
return strings.IndexFunc(s, func(r rune) bool {
|
||||||
|
return !unicode.IsDigit(r)
|
||||||
|
}) == -1
|
||||||
|
}
|
|
@ -21,7 +21,7 @@ func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (int32,
|
||||||
return 0, 0, ErrPlatformNotSupport
|
return 0, 0, ErrPlatformNotSupport
|
||||||
}
|
}
|
||||||
|
|
||||||
func findProcessName(network string, ip netip.Addr, port int) (string, error) {
|
func findProcessName(network string, ip netip.Addr, port int) (int32, string, error) {
|
||||||
var spath string
|
var spath string
|
||||||
switch network {
|
switch network {
|
||||||
case TCP:
|
case TCP:
|
||||||
|
@ -29,14 +29,14 @@ func findProcessName(network string, ip netip.Addr, port int) (string, error) {
|
||||||
case UDP:
|
case UDP:
|
||||||
spath = "net.inet.udp.pcblist_n"
|
spath = "net.inet.udp.pcblist_n"
|
||||||
default:
|
default:
|
||||||
return "", ErrInvalidNetwork
|
return -1, "", ErrInvalidNetwork
|
||||||
}
|
}
|
||||||
|
|
||||||
isIPv4 := ip.Is4()
|
isIPv4 := ip.Is4()
|
||||||
|
|
||||||
value, err := syscall.Sysctl(spath)
|
value, err := syscall.Sysctl(spath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return -1, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := []byte(value)
|
buf := []byte(value)
|
||||||
|
@ -81,10 +81,11 @@ func findProcessName(network string, ip netip.Addr, port int) (string, error) {
|
||||||
|
|
||||||
// xsocket_n.so_last_pid
|
// xsocket_n.so_last_pid
|
||||||
pid := readNativeUint32(buf[so+68 : so+72])
|
pid := readNativeUint32(buf[so+68 : so+72])
|
||||||
return getExecPathFromPID(pid)
|
pp, err := getExecPathFromPID(pid)
|
||||||
|
return -1, pp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", ErrNotFound
|
return -1, "", ErrNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
func getExecPathFromPID(pid uint32) (string, error) {
|
func getExecPathFromPID(pid uint32) (string, error) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (int32,
|
||||||
return 0, 0, ErrPlatformNotSupport
|
return 0, 0, ErrPlatformNotSupport
|
||||||
}
|
}
|
||||||
|
|
||||||
func findProcessName(network string, ip netip.Addr, srcPort int) (string, error) {
|
func findProcessName(network string, ip netip.Addr, srcPort int) (int32, string, error) {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
if err := initSearcher(); err != nil {
|
if err := initSearcher(); err != nil {
|
||||||
log.Errorln("Initialize PROCESS-NAME failed: %s", err.Error())
|
log.Errorln("Initialize PROCESS-NAME failed: %s", err.Error())
|
||||||
|
@ -35,7 +35,7 @@ func findProcessName(network string, ip netip.Addr, srcPort int) (string, error)
|
||||||
})
|
})
|
||||||
|
|
||||||
if defaultSearcher == nil {
|
if defaultSearcher == nil {
|
||||||
return "", ErrPlatformNotSupport
|
return -1, "", ErrPlatformNotSupport
|
||||||
}
|
}
|
||||||
|
|
||||||
var spath string
|
var spath string
|
||||||
|
@ -46,21 +46,22 @@ func findProcessName(network string, ip netip.Addr, srcPort int) (string, error)
|
||||||
case UDP:
|
case UDP:
|
||||||
spath = "net.inet.udp.pcblist"
|
spath = "net.inet.udp.pcblist"
|
||||||
default:
|
default:
|
||||||
return "", ErrInvalidNetwork
|
return -1, "", ErrInvalidNetwork
|
||||||
}
|
}
|
||||||
|
|
||||||
value, err := syscall.Sysctl(spath)
|
value, err := syscall.Sysctl(spath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return -1, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := []byte(value)
|
buf := []byte(value)
|
||||||
pid, err := defaultSearcher.Search(buf, ip, uint16(srcPort), isTCP)
|
pid, err := defaultSearcher.Search(buf, ip, uint16(srcPort), isTCP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return -1, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return getExecPathFromPID(pid)
|
pp, err := getExecPathFromPID(pid)
|
||||||
|
return -1, pp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getExecPathFromPID(pid uint32) (string, error) {
|
func getExecPathFromPID(pid uint32) (string, error) {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//go:build !android
|
||||||
|
|
||||||
package process
|
package process
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -32,12 +34,13 @@ const (
|
||||||
pathProc = "/proc"
|
pathProc = "/proc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func findProcessName(network string, ip netip.Addr, srcPort int) (string, error) {
|
func findProcessName(network string, ip netip.Addr, srcPort int) (int32, string, error) {
|
||||||
inode, uid, err := resolveSocketByNetlink(network, ip, srcPort)
|
inode, uid, err := resolveSocketByNetlink(network, ip, srcPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return -1, "", err
|
||||||
}
|
}
|
||||||
return resolveProcessNameByProcSearch(inode, uid)
|
pp, err := resolveProcessNameByProcSearch(inode, uid)
|
||||||
|
return uid, pp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (int32, int32, error) {
|
func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (int32, int32, error) {
|
||||||
|
|
|
@ -4,8 +4,8 @@ package process
|
||||||
|
|
||||||
import "net/netip"
|
import "net/netip"
|
||||||
|
|
||||||
func findProcessName(network string, ip netip.Addr, srcPort int) (string, error) {
|
func findProcessName(network string, ip netip.Addr, srcPort int) (int32, string, error) {
|
||||||
return "", ErrPlatformNotSupport
|
return -1, "", ErrPlatformNotSupport
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (int32, int32, error) {
|
func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (int32, int32, error) {
|
||||||
|
|
|
@ -62,7 +62,7 @@ func initWin32API() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findProcessName(network string, ip netip.Addr, srcPort int) (string, error) {
|
func findProcessName(network string, ip netip.Addr, srcPort int) (int32, string, error) {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
err := initWin32API()
|
err := initWin32API()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -86,21 +86,22 @@ func findProcessName(network string, ip netip.Addr, srcPort int) (string, error)
|
||||||
fn = getExUDPTable
|
fn = getExUDPTable
|
||||||
class = udpTablePid
|
class = udpTablePid
|
||||||
default:
|
default:
|
||||||
return "", ErrInvalidNetwork
|
return -1, "", ErrInvalidNetwork
|
||||||
}
|
}
|
||||||
|
|
||||||
buf, err := getTransportTable(fn, family, class)
|
buf, err := getTransportTable(fn, family, class)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return -1, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
s := newSearcher(family == windows.AF_INET, network == TCP)
|
s := newSearcher(family == windows.AF_INET, network == TCP)
|
||||||
|
|
||||||
pid, err := s.Search(buf, ip, uint16(srcPort))
|
pid, err := s.Search(buf, ip, uint16(srcPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return -1, "", err
|
||||||
}
|
}
|
||||||
return getExecPathFromPID(pid)
|
pp, err := getExecPathFromPID(pid)
|
||||||
|
return -1, pp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
type searcher struct {
|
type searcher struct {
|
||||||
|
|
|
@ -52,6 +52,7 @@ type General struct {
|
||||||
GeodataMode bool `json:"geodata-mode"`
|
GeodataMode bool `json:"geodata-mode"`
|
||||||
GeodataLoader string `json:"geodata-loader"`
|
GeodataLoader string `json:"geodata-loader"`
|
||||||
TCPConcurrent bool `json:"tcp-concurrent"`
|
TCPConcurrent bool `json:"tcp-concurrent"`
|
||||||
|
EnableProcess bool `json:"enable-process"`
|
||||||
Tun Tun `json:"tun"`
|
Tun Tun `json:"tun"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,6 +207,7 @@ type RawConfig struct {
|
||||||
GeodataMode bool `yaml:"geodata-mode"`
|
GeodataMode bool `yaml:"geodata-mode"`
|
||||||
GeodataLoader string `yaml:"geodata-loader"`
|
GeodataLoader string `yaml:"geodata-loader"`
|
||||||
TCPConcurrent bool `yaml:"tcp-concurrent" json:"tcp-concurrent"`
|
TCPConcurrent bool `yaml:"tcp-concurrent" json:"tcp-concurrent"`
|
||||||
|
EnableProcess bool `yaml:"enable-process" json:"enable-process"`
|
||||||
|
|
||||||
Sniffer RawSniffer `yaml:"sniffer"`
|
Sniffer RawSniffer `yaml:"sniffer"`
|
||||||
ProxyProvider map[string]map[string]any `yaml:"proxy-providers"`
|
ProxyProvider map[string]map[string]any `yaml:"proxy-providers"`
|
||||||
|
@ -255,6 +257,7 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
|
||||||
Proxy: []map[string]any{},
|
Proxy: []map[string]any{},
|
||||||
ProxyGroup: []map[string]any{},
|
ProxyGroup: []map[string]any{},
|
||||||
TCPConcurrent: false,
|
TCPConcurrent: false,
|
||||||
|
EnableProcess: true,
|
||||||
Tun: RawTun{
|
Tun: RawTun{
|
||||||
Enable: false,
|
Enable: false,
|
||||||
Device: "",
|
Device: "",
|
||||||
|
@ -410,6 +413,7 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
|
||||||
GeodataMode: cfg.GeodataMode,
|
GeodataMode: cfg.GeodataMode,
|
||||||
GeodataLoader: cfg.GeodataLoader,
|
GeodataLoader: cfg.GeodataLoader,
|
||||||
TCPConcurrent: cfg.TCPConcurrent,
|
TCPConcurrent: cfg.TCPConcurrent,
|
||||||
|
EnableProcess: cfg.EnableProcess,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package executor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/Dreamacro/clash/component/process"
|
||||||
"github.com/Dreamacro/clash/listener/inner"
|
"github.com/Dreamacro/clash/listener/inner"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
|
@ -270,6 +271,7 @@ func updateSniffer(sniffer *config.Sniffer) {
|
||||||
|
|
||||||
func updateGeneral(general *config.General, force bool) {
|
func updateGeneral(general *config.General, force bool) {
|
||||||
log.SetLevel(general.LogLevel)
|
log.SetLevel(general.LogLevel)
|
||||||
|
process.EnableFindProcess(general.EnableProcess)
|
||||||
tunnel.SetMode(general.Mode)
|
tunnel.SetMode(general.Mode)
|
||||||
dialer.DisableIPv6 = !general.IPv6
|
dialer.DisableIPv6 = !general.IPv6
|
||||||
if !dialer.DisableIPv6 {
|
if !dialer.DisableIPv6 {
|
||||||
|
|
|
@ -3,9 +3,11 @@ package rules
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
"github.com/Dreamacro/clash/log"
|
||||||
RC "github.com/Dreamacro/clash/rule/common"
|
RC "github.com/Dreamacro/clash/rule/common"
|
||||||
"github.com/Dreamacro/clash/rule/logic"
|
"github.com/Dreamacro/clash/rule/logic"
|
||||||
RP "github.com/Dreamacro/clash/rule/provider"
|
RP "github.com/Dreamacro/clash/rule/provider"
|
||||||
|
"runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ParseRule(tp, payload, target string, params []string) (C.Rule, error) {
|
func ParseRule(tp, payload, target string, params []string) (C.Rule, error) {
|
||||||
|
@ -42,7 +44,11 @@ func ParseRule(tp, payload, target string, params []string) (C.Rule, error) {
|
||||||
case "NETWORK":
|
case "NETWORK":
|
||||||
parsed, parseErr = RC.NewNetworkType(payload, target)
|
parsed, parseErr = RC.NewNetworkType(payload, target)
|
||||||
case "UID":
|
case "UID":
|
||||||
|
if runtime.GOOS == "linux" || runtime.GOOS == "android" {
|
||||||
parsed, parseErr = RC.NewUid(payload, target)
|
parsed, parseErr = RC.NewUid(payload, target)
|
||||||
|
} else {
|
||||||
|
log.Warnln("uid rule not support this platform")
|
||||||
|
}
|
||||||
case "AND":
|
case "AND":
|
||||||
parsed, parseErr = logic.NewAND(payload, target)
|
parsed, parseErr = logic.NewAND(payload, target)
|
||||||
case "OR":
|
case "OR":
|
||||||
|
|
|
@ -170,7 +170,7 @@ func preHandleMetadata(metadata *C.Metadata) error {
|
||||||
// pre resolve process name
|
// pre resolve process name
|
||||||
srcPort, err := strconv.Atoi(metadata.SrcPort)
|
srcPort, err := strconv.Atoi(metadata.SrcPort)
|
||||||
if err == nil && P.ShouldFindProcess(metadata) {
|
if err == nil && P.ShouldFindProcess(metadata) {
|
||||||
path, err := P.FindProcessName(metadata.NetWork.String(), metadata.SrcIP, srcPort)
|
uid, path, err := P.FindProcessName(metadata.NetWork.String(), metadata.SrcIP, srcPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if failTotal < 20 {
|
if failTotal < 20 {
|
||||||
log.Debugln("[Process] find process %s: %v", metadata.String(), err)
|
log.Debugln("[Process] find process %s: %v", metadata.String(), err)
|
||||||
|
@ -179,6 +179,9 @@ func preHandleMetadata(metadata *C.Metadata) error {
|
||||||
} else {
|
} else {
|
||||||
metadata.Process = filepath.Base(path)
|
metadata.Process = filepath.Base(path)
|
||||||
metadata.ProcessPath = path
|
metadata.ProcessPath = path
|
||||||
|
if uid != -1 {
|
||||||
|
metadata.Uid = &uid
|
||||||
|
}
|
||||||
if procesCache != metadata.Process {
|
if procesCache != metadata.Process {
|
||||||
log.Debugln("[Process] %s from process %s", metadata.String(), path)
|
log.Debugln("[Process] %s from process %s", metadata.String(), path)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue