Merge remote-tracking branch 'clash/dev' into Alpha
# Conflicts: # .github/workflows/codeql-analysis.yml # .github/workflows/docker.yml # .github/workflows/linter.yml # .github/workflows/stale.yml # Makefile # component/dialer/dialer.go # config/config.go # constant/metadata.go # constant/rule.go # rule/common/domain.go # rule/common/domain_keyword.go # rule/common/domain_suffix.go # rule/common/final.go # rule/common/ipcidr.go # rule/geoip.go # rule/parser.go # rule/port.go # rule/process.go
This commit is contained in:
commit
f01ac69654
32 changed files with 123 additions and 175 deletions
2
.github/workflows/Alpha.yml
vendored
2
.github/workflows/Alpha.yml
vendored
|
@ -15,7 +15,7 @@ jobs:
|
|||
go-version: ${{ steps.version.outputs.go_version }}
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Cache go module
|
||||
uses: actions/cache@v2
|
||||
|
|
14
.golangci.yaml
Normal file
14
.golangci.yaml
Normal file
|
@ -0,0 +1,14 @@
|
|||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- gofumpt
|
||||
- megacheck
|
||||
- govet
|
||||
- gci
|
||||
|
||||
linters-settings:
|
||||
gci:
|
||||
sections:
|
||||
- standard
|
||||
- prefix(github.com/Dreamacro/clash)
|
||||
- default
|
|
@ -12,7 +12,7 @@ RUN go mod download && \
|
|||
FROM alpine:latest
|
||||
LABEL org.opencontainers.image.source="https://github.com/Dreamacro/clash"
|
||||
|
||||
RUN apk add --no-cache ca-certificates
|
||||
RUN apk add --no-cache ca-certificates tzdata
|
||||
COPY --from=builder /Country.mmdb /root/.config/clash/
|
||||
COPY --from=builder /clash /
|
||||
ENTRYPOINT ["/clash"]
|
||||
|
|
|
@ -4,9 +4,9 @@ import (
|
|||
"net"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/Dreamacro/clash/component/iface"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type controlFn = func(network, address string, c syscall.RawConn) error
|
||||
|
|
|
@ -3,7 +3,6 @@ package process
|
|||
import (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
|
@ -96,7 +95,7 @@ func getExecPathFromPID(pid uint32) (string, error) {
|
|||
return "", errno
|
||||
}
|
||||
|
||||
return filepath.Base(unix.ByteSliceToString(buf)), nil
|
||||
return unix.ByteSliceToString(buf), nil
|
||||
}
|
||||
|
||||
func readNativeUint32(b []byte) uint32 {
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -77,7 +76,7 @@ func getExecPathFromPID(pid uint32) (string, error) {
|
|||
return "", errno
|
||||
}
|
||||
|
||||
return filepath.Base(string(buf[:size-1])), nil
|
||||
return string(buf[:size-1]), nil
|
||||
}
|
||||
|
||||
func readNativeUint32(b []byte) uint32 {
|
||||
|
|
|
@ -4,12 +4,12 @@ import (
|
|||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unicode"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Dreamacro/clash/common/pool"
|
||||
|
@ -25,17 +25,6 @@ var nativeEndian = func() binary.ByteOrder {
|
|||
return binary.LittleEndian
|
||||
}()
|
||||
|
||||
type (
|
||||
SocketResolver func(network string, ip net.IP, srcPort int) (inode, uid int, err error)
|
||||
ProcessNameResolver func(inode, uid int) (name string, err error)
|
||||
)
|
||||
|
||||
// export for android
|
||||
var (
|
||||
DefaultSocketResolver SocketResolver = resolveSocketByNetlink
|
||||
DefaultProcessNameResolver ProcessNameResolver = resolveProcessNameByProcSearch
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfSocketDiagRequest = syscall.SizeofNlMsghdr + 8 + 48
|
||||
socketDiagByFamily = 20
|
||||
|
@ -43,15 +32,15 @@ const (
|
|||
)
|
||||
|
||||
func findProcessName(network string, ip net.IP, srcPort int) (string, error) {
|
||||
inode, uid, err := DefaultSocketResolver(network, ip, srcPort)
|
||||
inode, uid, err := resolveSocketByNetlink(network, ip, srcPort)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return DefaultProcessNameResolver(inode, uid)
|
||||
return resolveProcessNameByProcSearch(inode, uid)
|
||||
}
|
||||
|
||||
func resolveSocketByNetlink(network string, ip net.IP, srcPort int) (int, int, error) {
|
||||
func resolveSocketByNetlink(network string, ip net.IP, srcPort int) (int32, int32, error) {
|
||||
var family byte
|
||||
var protocol byte
|
||||
|
||||
|
@ -74,13 +63,12 @@ func resolveSocketByNetlink(network string, ip net.IP, srcPort int) (int, int, e
|
|||
|
||||
socket, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_DGRAM, syscall.NETLINK_INET_DIAG)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
return 0, 0, fmt.Errorf("dial netlink: %w", err)
|
||||
}
|
||||
defer syscall.Close(socket)
|
||||
|
||||
syscall.SetNonblock(socket, true)
|
||||
syscall.SetsockoptTimeval(socket, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &syscall.Timeval{Usec: 50})
|
||||
syscall.SetsockoptTimeval(socket, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &syscall.Timeval{Usec: 50})
|
||||
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,
|
||||
|
@ -92,7 +80,7 @@ func resolveSocketByNetlink(network string, ip net.IP, srcPort int) (int, int, e
|
|||
}
|
||||
|
||||
if _, err := syscall.Write(socket, req); err != nil {
|
||||
return 0, 0, err
|
||||
return 0, 0, fmt.Errorf("write request: %w", err)
|
||||
}
|
||||
|
||||
rb := pool.Get(pool.RelayBufferSize)
|
||||
|
@ -100,24 +88,27 @@ func resolveSocketByNetlink(network string, ip net.IP, srcPort int) (int, int, e
|
|||
|
||||
n, err := syscall.Read(socket, rb)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
return 0, 0, fmt.Errorf("read response: %w", err)
|
||||
}
|
||||
|
||||
messages, err := syscall.ParseNetlinkMessage(rb[:n])
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
return 0, 0, fmt.Errorf("parse netlink message: %w", err)
|
||||
} else if len(messages) == 0 {
|
||||
return 0, 0, io.ErrUnexpectedEOF
|
||||
return 0, 0, fmt.Errorf("unexcepted netlink response")
|
||||
}
|
||||
|
||||
message := messages[0]
|
||||
if message.Header.Type&syscall.NLMSG_ERROR != 0 {
|
||||
return 0, 0, syscall.ESRCH
|
||||
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 int(uid), int(inode), nil
|
||||
return uid, inode, nil
|
||||
}
|
||||
|
||||
func packSocketDiagRequest(family, protocol byte, source net.IP, sourcePort uint16) []byte {
|
||||
|
@ -155,20 +146,20 @@ func packSocketDiagRequest(family, protocol byte, source net.IP, sourcePort uint
|
|||
return buf
|
||||
}
|
||||
|
||||
func unpackSocketDiagResponse(msg *syscall.NetlinkMessage) (inode, uid uint32) {
|
||||
func unpackSocketDiagResponse(msg *syscall.NetlinkMessage) (inode, uid int32) {
|
||||
if len(msg.Data) < 72 {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
data := msg.Data
|
||||
|
||||
uid = nativeEndian.Uint32(data[64:68])
|
||||
inode = nativeEndian.Uint32(data[68:72])
|
||||
uid = int32(nativeEndian.Uint32(data[64:68]))
|
||||
inode = int32(nativeEndian.Uint32(data[68:72]))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func resolveProcessNameByProcSearch(inode, uid int) (string, error) {
|
||||
func resolveProcessNameByProcSearch(inode, uid int32) (string, error) {
|
||||
files, err := os.ReadDir(pathProc)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -205,38 +196,16 @@ func resolveProcessNameByProcSearch(inode, uid int) (string, error) {
|
|||
}
|
||||
|
||||
if bytes.Equal(buffer[:n], socket) {
|
||||
cmdline, err := os.ReadFile(path.Join(processPath, "cmdline"))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return splitCmdline(cmdline), nil
|
||||
return os.Readlink(path.Join(processPath, "exe"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", syscall.ESRCH
|
||||
}
|
||||
|
||||
func splitCmdline(cmdline []byte) string {
|
||||
indexOfEndOfString := len(cmdline)
|
||||
|
||||
for i, c := range cmdline {
|
||||
if c == 0 {
|
||||
indexOfEndOfString = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return filepath.Base(string(cmdline[:indexOfEndOfString]))
|
||||
return "", fmt.Errorf("process of uid(%d),inode(%d) not found", uid, inode)
|
||||
}
|
||||
|
||||
func isPid(s string) bool {
|
||||
for _, s := range s {
|
||||
if s < '0' || s > '9' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
return strings.IndexFunc(s, func(r rune) bool {
|
||||
return !unicode.IsDigit(r)
|
||||
}) == -1
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package process
|
|||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
@ -220,5 +219,5 @@ func getExecPathFromPID(pid uint32) (string, error) {
|
|||
if r1 == 0 {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Base(syscall.UTF16ToString(buf[:size])), nil
|
||||
return syscall.UTF16ToString(buf[:size]), nil
|
||||
}
|
||||
|
|
|
@ -176,6 +176,7 @@ type RawConfig struct {
|
|||
GeodataMode string `yaml:"geodata-mode"`
|
||||
GeodataLoader string `yaml:"geodata-loader"`
|
||||
AutoIptables bool `yaml:"auto-iptables"`
|
||||
RoutingMark int `yaml:"routing-mark"`
|
||||
|
||||
ProxyProvider map[string]map[string]interface{} `yaml:"proxy-providers"`
|
||||
RuleProvider map[string]map[string]interface{} `yaml:"rule-providers"`
|
||||
|
@ -240,7 +241,7 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
|
|||
},
|
||||
NameServer: []string{
|
||||
"223.5.5.5",
|
||||
"119.29.29",
|
||||
"119.29.29.29",
|
||||
},
|
||||
FakeIPFilter: []string{
|
||||
"dns.msftnsci.com",
|
||||
|
@ -351,6 +352,7 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
|
|||
Interface: cfg.Interface,
|
||||
GeodataLoader: cfg.GeodataLoader,
|
||||
AutoIptables: cfg.AutoIptables,
|
||||
RoutingMark: cfg.RoutingMark,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ type Metadata struct {
|
|||
Host string `json:"host"`
|
||||
Process string `json:"process"`
|
||||
DNSMode DNSMode `json:"dnsMode"`
|
||||
ProcessPath string `json:"processPath"`
|
||||
}
|
||||
|
||||
func (m *Metadata) RemoteAddress() string {
|
||||
|
|
|
@ -12,6 +12,7 @@ const (
|
|||
SrcPort
|
||||
DstPort
|
||||
Process
|
||||
ProcessPath
|
||||
Script
|
||||
RuleSet
|
||||
Network
|
||||
|
@ -46,6 +47,8 @@ func (rt RuleType) String() string {
|
|||
return "DstPort"
|
||||
case Process:
|
||||
return "Process"
|
||||
case ProcessPath:
|
||||
return "ProcessPath"
|
||||
case Script:
|
||||
return "Script"
|
||||
case MATCH:
|
||||
|
@ -71,5 +74,6 @@ type Rule interface {
|
|||
Adapter() string
|
||||
Payload() string
|
||||
ShouldResolveIP() bool
|
||||
ShouldFindProcess() bool
|
||||
RuleExtra() *RuleExtra
|
||||
}
|
||||
|
|
|
@ -232,6 +232,7 @@ func updateGeneral(general *config.General, Tun *config.Tun, force bool) {
|
|||
}
|
||||
|
||||
dialer.DefaultInterface.Store(general.Interface)
|
||||
dialer.DefaultRoutingMark.Store(int32(general.RoutingMark))
|
||||
|
||||
log.Infoln("Use interface name: %s", general.Interface)
|
||||
|
||||
|
|
|
@ -19,7 +19,12 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) {
|
|||
client := newClient(c.RemoteAddr(), in)
|
||||
defer client.CloseIdleConnections()
|
||||
|
||||
conn := N.NewBufferedConn(c)
|
||||
var conn *N.BufferedConn
|
||||
if bufConn, ok := c.(*N.BufferedConn); ok {
|
||||
conn = bufConn
|
||||
} else {
|
||||
conn = N.NewBufferedConn(c)
|
||||
}
|
||||
|
||||
keepAlive := true
|
||||
trusted := cache == nil // disable authenticate if cache is nil
|
||||
|
|
|
@ -64,6 +64,8 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) {
|
|||
}
|
||||
|
||||
func handleConn(conn net.Conn, in chan<- C.ConnContext, cache *cache.Cache) {
|
||||
conn.(*net.TCPConn).SetKeepAlive(true)
|
||||
|
||||
bufConn := N.NewBufferedConn(conn)
|
||||
head, err := bufConn.Peek(1)
|
||||
if err != nil {
|
||||
|
|
|
@ -61,6 +61,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) {
|
|||
}
|
||||
|
||||
func handleSocks(conn net.Conn, in chan<- C.ConnContext) {
|
||||
conn.(*net.TCPConn).SetKeepAlive(true)
|
||||
bufConn := N.NewBufferedConn(conn)
|
||||
head, err := bufConn.Peek(1)
|
||||
if err != nil {
|
||||
|
@ -84,9 +85,6 @@ func HandleSocks4(conn net.Conn, in chan<- C.ConnContext) {
|
|||
conn.Close()
|
||||
return
|
||||
}
|
||||
if c, ok := conn.(*net.TCPConn); ok {
|
||||
c.SetKeepAlive(true)
|
||||
}
|
||||
in <- inbound.NewSocket(socks5.ParseAddr(addr), conn, C.SOCKS4)
|
||||
}
|
||||
|
||||
|
@ -96,9 +94,6 @@ func HandleSocks5(conn net.Conn, in chan<- C.ConnContext) {
|
|||
conn.Close()
|
||||
return
|
||||
}
|
||||
if c, ok := conn.(*net.TCPConn); ok {
|
||||
c.SetKeepAlive(true)
|
||||
}
|
||||
if command == socks5.CmdUDPAssociate {
|
||||
defer conn.Close()
|
||||
io.Copy(io.Discard, conn)
|
||||
|
|
|
@ -39,6 +39,10 @@ func (d *Domain) RuleExtra() *C.RuleExtra {
|
|||
return d.ruleExtra
|
||||
}
|
||||
|
||||
func (d *Domain) ShouldFindProcess() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func NewDomain(domain string, adapter string, ruleExtra *C.RuleExtra) *Domain {
|
||||
return &Domain{
|
||||
domain: strings.ToLower(domain),
|
||||
|
|
|
@ -36,11 +36,15 @@ func (dk *DomainKeyword) ShouldResolveIP() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (dk *DomainKeyword) ShouldFindProcess() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (dk *DomainKeyword) RuleExtra() *C.RuleExtra {
|
||||
return dk.ruleExtra
|
||||
}
|
||||
|
||||
func NewDomainKeyword(keyword string, adapter string, ruleExtra *C.RuleExtra) *DomainKeyword {
|
||||
func NewDomainKeyword(keyword string, adapter string) *DomainKeyword {
|
||||
return &DomainKeyword{
|
||||
keyword: strings.ToLower(keyword),
|
||||
adapter: adapter,
|
||||
|
|
|
@ -40,6 +40,11 @@ func (ds *DomainSuffix) RuleExtra() *C.RuleExtra {
|
|||
return ds.ruleExtra
|
||||
}
|
||||
|
||||
|
||||
func (ds *DomainSuffix) ShouldFindProcess() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func NewDomainSuffix(suffix string, adapter string, ruleExtra *C.RuleExtra) *DomainSuffix {
|
||||
return &DomainSuffix{
|
||||
suffix: strings.ToLower(suffix),
|
||||
|
|
|
@ -29,6 +29,10 @@ func (f *Match) ShouldResolveIP() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (f *Match) ShouldFindProcess() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *Match) RuleExtra() *C.RuleExtra {
|
||||
return f.ruleExtra
|
||||
}
|
||||
|
|
|
@ -55,6 +55,10 @@ func (i *IPCIDR) ShouldResolveIP() bool {
|
|||
return !i.noResolveIP
|
||||
}
|
||||
|
||||
func (i *IPCIDR) ShouldFindProcess() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (i *IPCIDR) RuleExtra() *C.RuleExtra {
|
||||
return i.ruleExtra
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package rule
|
||||
package rules
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -42,7 +42,9 @@ func ParseRule(tp, payload, target string, params []string) (C.Rule, error) {
|
|||
case "DST-PORT":
|
||||
parsed, parseErr = RC.NewPort(payload, target, false, ruleExtra)
|
||||
case "PROCESS-NAME":
|
||||
parsed, parseErr = RC.NewProcess(payload, target, ruleExtra)
|
||||
parsed, parseErr = RC.NewProcess(payload, target, true,ruleExtra)
|
||||
case "PROCESS-PATH":
|
||||
parsed, parseErr = RC.NewProcess(payload, target, false,ruleExtra)
|
||||
case "MATCH":
|
||||
parsed = RC.NewMatch(target, ruleExtra)
|
||||
case "RULE-SET":
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
{
|
||||
"inbounds": [
|
||||
{
|
||||
"port": 10002,
|
||||
"listen": "0.0.0.0",
|
||||
"protocol": "vmess",
|
||||
"settings": {
|
||||
"clients": [
|
||||
{
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
"alterId": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": "tcp"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outbounds": [
|
||||
{
|
||||
"protocol": "freedom"
|
||||
}
|
||||
],
|
||||
"log": {
|
||||
"loglevel": "debug"
|
||||
}
|
||||
}
|
|
@ -7,8 +7,7 @@
|
|||
"settings": {
|
||||
"clients": [
|
||||
{
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
"alterId": 32
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
"settings": {
|
||||
"clients": [
|
||||
{
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
"alterId": 32
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
"settings": {
|
||||
"clients": [
|
||||
{
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
"alterId": 32
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
"settings": {
|
||||
"clients": [
|
||||
{
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
"alterId": 32
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
"settings": {
|
||||
"clients": [
|
||||
{
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
"alterId": 32
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
"settings": {
|
||||
"clients": [
|
||||
{
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
"alterId": 32
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
"settings": {
|
||||
"clients": [
|
||||
{
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
"alterId": 32
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
"settings": {
|
||||
"clients": [
|
||||
{
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
"alterId": 32
|
||||
"id": "b831381d-6324-4d53-ad4f-8cda48b30811"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -34,51 +34,12 @@ func TestClash_Vmess(t *testing.T) {
|
|||
})
|
||||
|
||||
proxy, err := outbound.NewVmess(outbound.VmessOption{
|
||||
Name: "vmess",
|
||||
Server: localIP.String(),
|
||||
Port: 10002,
|
||||
UUID: "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
Cipher: "auto",
|
||||
AlterID: 32,
|
||||
UDP: true,
|
||||
})
|
||||
if err != nil {
|
||||
assert.FailNow(t, err.Error())
|
||||
}
|
||||
|
||||
time.Sleep(waitTime)
|
||||
testSuit(t, proxy)
|
||||
}
|
||||
|
||||
func TestClash_VmessAEAD(t *testing.T) {
|
||||
configPath := C.Path.Resolve("vmess-aead.json")
|
||||
|
||||
cfg := &container.Config{
|
||||
Image: ImageVmess,
|
||||
ExposedPorts: defaultExposedPorts,
|
||||
}
|
||||
hostCfg := &container.HostConfig{
|
||||
PortBindings: defaultPortBindings,
|
||||
Binds: []string{fmt.Sprintf("%s:/etc/v2ray/config.json", configPath)},
|
||||
}
|
||||
|
||||
id, err := startContainer(cfg, hostCfg, "vmess-aead")
|
||||
if err != nil {
|
||||
assert.FailNow(t, err.Error())
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
cleanContainer(id)
|
||||
})
|
||||
|
||||
proxy, err := outbound.NewVmess(outbound.VmessOption{
|
||||
Name: "vmess",
|
||||
Server: localIP.String(),
|
||||
Port: 10002,
|
||||
UUID: "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
Cipher: "auto",
|
||||
AlterID: 0,
|
||||
UDP: true,
|
||||
Name: "vmess",
|
||||
Server: localIP.String(),
|
||||
Port: 10002,
|
||||
UUID: "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
Cipher: "auto",
|
||||
UDP: true,
|
||||
})
|
||||
if err != nil {
|
||||
assert.FailNow(t, err.Error())
|
||||
|
@ -114,7 +75,6 @@ func TestClash_VmessTLS(t *testing.T) {
|
|||
Port: 10002,
|
||||
UUID: "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
Cipher: "auto",
|
||||
AlterID: 32,
|
||||
TLS: true,
|
||||
SkipCertVerify: true,
|
||||
ServerName: "example.org",
|
||||
|
@ -154,7 +114,6 @@ func TestClash_VmessHTTP2(t *testing.T) {
|
|||
Port: 10002,
|
||||
UUID: "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
Cipher: "auto",
|
||||
AlterID: 32,
|
||||
Network: "h2",
|
||||
TLS: true,
|
||||
SkipCertVerify: true,
|
||||
|
@ -197,7 +156,6 @@ func TestClash_VmessHTTP(t *testing.T) {
|
|||
Port: 10002,
|
||||
UUID: "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
Cipher: "auto",
|
||||
AlterID: 32,
|
||||
Network: "http",
|
||||
UDP: true,
|
||||
HTTPOpts: outbound.HTTPOptions{
|
||||
|
@ -250,7 +208,6 @@ func TestClash_VmessWebsocket(t *testing.T) {
|
|||
Port: 10002,
|
||||
UUID: "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
Cipher: "auto",
|
||||
AlterID: 32,
|
||||
Network: "ws",
|
||||
UDP: true,
|
||||
})
|
||||
|
@ -288,7 +245,6 @@ func TestClash_VmessWebsocketTLS(t *testing.T) {
|
|||
Port: 10002,
|
||||
UUID: "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
Cipher: "auto",
|
||||
AlterID: 32,
|
||||
Network: "ws",
|
||||
TLS: true,
|
||||
SkipCertVerify: true,
|
||||
|
@ -328,7 +284,6 @@ func TestClash_VmessGrpc(t *testing.T) {
|
|||
Port: 10002,
|
||||
UUID: "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
Cipher: "auto",
|
||||
AlterID: 32,
|
||||
Network: "grpc",
|
||||
TLS: true,
|
||||
SkipCertVerify: true,
|
||||
|
@ -370,7 +325,6 @@ func TestClash_VmessWebsocket0RTT(t *testing.T) {
|
|||
Port: 10002,
|
||||
UUID: "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
Cipher: "auto",
|
||||
AlterID: 32,
|
||||
Network: "ws",
|
||||
UDP: true,
|
||||
ServerName: "example.org",
|
||||
|
@ -411,7 +365,6 @@ func TestClash_VmessWebsocketXray0RTT(t *testing.T) {
|
|||
Port: 10002,
|
||||
UUID: "b831381d-6324-4d53-ad4f-8cda48b30811",
|
||||
Cipher: "auto",
|
||||
AlterID: 32,
|
||||
Network: "ws",
|
||||
UDP: true,
|
||||
ServerName: "example.org",
|
||||
|
|
|
@ -6,11 +6,13 @@ import (
|
|||
R "github.com/Dreamacro/clash/rule/common"
|
||||
"net"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Dreamacro/clash/adapter/inbound"
|
||||
"github.com/Dreamacro/clash/component/nat"
|
||||
P "github.com/Dreamacro/clash/component/process"
|
||||
"github.com/Dreamacro/clash/component/resolver"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/constant/provider"
|
||||
|
@ -329,6 +331,7 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) {
|
|||
defer configMux.RUnlock()
|
||||
|
||||
var resolved bool
|
||||
var processFound bool
|
||||
|
||||
if node := resolver.DefaultHosts.Search(metadata.Host); node != nil {
|
||||
ip := node.Data.(net.IP)
|
||||
|
@ -351,6 +354,21 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) {
|
|||
resolved = true
|
||||
}
|
||||
|
||||
if !processFound && rule.ShouldFindProcess() {
|
||||
processFound = true
|
||||
|
||||
srcPort, err := strconv.Atoi(metadata.SrcPort)
|
||||
if err == nil {
|
||||
path, err := P.FindProcessName(metadata.NetWork.String(), metadata.SrcIP, srcPort)
|
||||
if err != nil {
|
||||
log.Debugln("[Process] find process %s: %v", metadata.String(), err)
|
||||
} else {
|
||||
log.Debugln("[Process] %s from process %s", metadata.String(), path)
|
||||
metadata.ProcessPath = path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if rule.Match(metadata) {
|
||||
adapter, ok := proxies[rule.Adapter()]
|
||||
if !ok {
|
||||
|
|
Loading…
Reference in a new issue