diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e4d796bc..b3696d13 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,6 +27,10 @@ jobs: - name: Get dependencies, run test run: | + # install python3.9 + sudo add-apt-repository -y ppa:deadsnakes/ppa + sudo apt install -y python3.9 python3.9-dev + # fetch python cross compile source files mkdir -p bin/python/ cd bin/python/ @@ -34,20 +38,21 @@ jobs: curl -LO https://raw.githubusercontent.com/yaling888/snack/main/python-3.9.7-darwin-arm64.tar.xz curl -LO https://raw.githubusercontent.com/yaling888/snack/main/python-3.9.7-windows-amd64.tar.xz curl -LO https://raw.githubusercontent.com/yaling888/snack/main/python-3.9.7-windows-386.tar.xz - curl -LO https://raw.githubusercontent.com/yaling888/snack/main/python-3.9.7-linux-amd64.tar.xz - curl -LO https://raw.githubusercontent.com/yaling888/snack/main/python-3.9.7-linux-arm64.tar.xz + #curl -LO https://raw.githubusercontent.com/yaling888/snack/main/python-3.9.7-linux-amd64.tar.xz + #curl -LO https://raw.githubusercontent.com/yaling888/snack/main/python-3.9.7-linux-arm64.tar.xz #curl -LO https://raw.githubusercontent.com/yaling888/snack/main/python-3.9.7-linux-386.tar.xz tar -Jxf python-3.9.7-darwin-amd64.tar.xz tar -Jxf python-3.9.7-darwin-arm64.tar.xz tar -Jxf python-3.9.7-windows-amd64.tar.xz tar -Jxf python-3.9.7-windows-386.tar.xz - tar -Jxf python-3.9.7-linux-amd64.tar.xz - tar -Jxf python-3.9.7-linux-arm64.tar.xz + #tar -Jxf python-3.9.7-linux-amd64.tar.xz + #tar -Jxf python-3.9.7-linux-arm64.tar.xz #tar -Jxf python-3.9.7-linux-386.tar.xz rm python-3.9.7-*.tar.xz cd ../../ - go test ./... + # go test + go test -tags build_local ./... # init xgo docker pull techknowlogick/xgo:latest @@ -66,6 +71,7 @@ jobs: BINDIR: bin run: | make -j releases + #ls -lahF bin/python/ - name: Prepare upload if: startsWith(github.ref, 'refs/tags/') == false diff --git a/Makefile b/Makefile index 50f749e8..dffe8e3b 100644 --- a/Makefile +++ b/Makefile @@ -18,8 +18,8 @@ STATIC_LDFLAGS='-X "github.com/Dreamacro/clash/constant.Version=$(VERSION)" \ PLATFORM_LIST = \ darwin-amd64 \ darwin-arm64 \ - linux-amd64 \ - linux-arm64 + linux-amd64 +# linux-arm64 # linux-386 WINDOWS_ARCH_LIST = \ @@ -44,7 +44,8 @@ linux-386: $(XGOCMD) -dest=$(BINDIR) -out=$(NAME) -trimpath=true -ldflags=$(STATIC_LDFLAGS) -targets=linux/386 $(BUILD_PACKAGE) linux-amd64: - GOARCH=amd64 GOOS=linux $(GOBUILD) -ldflags $(STATIC_LDFLAGS) -o $(BINDIR)/$(NAME)-$@ + $(GOBUILD) -ldflags $(RELEASE_LDFLAGS) -o $(BINDIR)/$(NAME)-$@ + #GOARCH=amd64 GOOS=linux $(GOBUILD) -ldflags $(RELEASE_LDFLAGS) -o $(BINDIR)/$(NAME)-$@ #$(XGOCMD) -dest=$(BINDIR) -out=$(NAME) -trimpath=true -ldflags=$(STATIC_LDFLAGS) -targets=linux/amd64 $(BUILD_PACKAGE) linux-arm64: @@ -76,6 +77,9 @@ all-arch: $(PLATFORM_LIST) $(WINDOWS_ARCH_LIST) releases: $(gz_releases) $(zip_releases) +vet: + $(GOCMD) vet -tags build_local ./... + lint: golangci-lint run --build-tags=build_local --disable-all -E govet -E gofumpt -E megacheck ./... diff --git a/component/script/build_xgo.go b/component/script/build_xgo.go index fe4ff5db..4a066c90 100644 --- a/component/script/build_xgo.go +++ b/component/script/build_xgo.go @@ -1,25 +1,25 @@ -//go:build !build_local -// +build !build_local +//go:build !build_local && cgo +// +build !build_local,cgo package script /* -//#cgo linux,amd64 pkg-config: python-3.9-embed +#cgo linux,amd64 pkg-config: python3-embed #cgo darwin,amd64 CFLAGS: -I/build/python/python-3.9.7-darwin-amd64/include/python3.9 #cgo darwin,arm64 CFLAGS: -I/build/python/python-3.9.7-darwin-arm64/include/python3.9 #cgo windows,amd64 CFLAGS: -I/build/python/python-3.9.7-windows-amd64/include -DMS_WIN64 #cgo windows,386 CFLAGS: -I/build/python/python-3.9.7-windows-386/include -#cgo linux,amd64 CFLAGS: -I/home/runner/work/clash/clash/bin/python/python-3.9.7-linux-amd64/include/python3.9 -#cgo linux,arm64 CFLAGS: -I/build/python/python-3.9.7-linux-arm64/include/python3.9 -#cgo linux,386 CFLAGS: -I/build/python/python-3.9.7-linux-386/include/python3.9 +//#cgo linux,amd64 CFLAGS: -I/home/runner/work/clash/clash/bin/python/python-3.9.7-linux-amd64/include/python3.9 +//#cgo linux,arm64 CFLAGS: -I/build/python/python-3.9.7-linux-arm64/include/python3.9 +//#cgo linux,386 CFLAGS: -I/build/python/python-3.9.7-linux-386/include/python3.9 #cgo darwin,amd64 LDFLAGS: -L/build/python/python-3.9.7-darwin-amd64/lib -lpython3.9 -ldl -framework CoreFoundation #cgo darwin,arm64 LDFLAGS: -L/build/python/python-3.9.7-darwin-arm64/lib -lpython3.9 -ldl -framework CoreFoundation #cgo windows,amd64 LDFLAGS: -L/build/python/python-3.9.7-windows-amd64/lib -lpython39 -lpthread -lm #cgo windows,386 LDFLAGS: -L/build/python/python-3.9.7-windows-386/lib -lpython39 -lpthread -lm -#cgo linux,amd64 LDFLAGS: -L/home/runner/work/clash/clash/bin/python/python-3.9.7-linux-amd64/lib -lpython3.9 -lpthread -ldl -lutil -lm -#cgo linux,arm64 LDFLAGS: -L/build/python/python-3.9.7-linux-arm64/lib -lpython3.9 -lpthread -ldl -lutil -lm -#cgo linux,386 LDFLAGS: -L/build/python/python-3.9.7-linux-386/lib -lpython3.9 -lcrypt -lpthread -ldl -lutil -lm +//#cgo linux,amd64 LDFLAGS: -L/home/runner/work/clash/clash/bin/python/python-3.9.7-linux-amd64/lib -lpython3.9 -lpthread -ldl -lutil -lm +//#cgo linux,arm64 LDFLAGS: -L/build/python/python-3.9.7-linux-arm64/lib -lpython3.9 -lpthread -ldl -lutil -lm +//#cgo linux,386 LDFLAGS: -L/build/python/python-3.9.7-linux-386/lib -lpython3.9 -lpthread -ldl -lutil -lm */ import "C" diff --git a/component/script/clash_module.c b/component/script/clash_module.c index 5bef9948..f15f0191 100644 --- a/component/script/clash_module.c +++ b/component/script/clash_module.c @@ -8,23 +8,30 @@ PyObject *main_fn; PyObject *clash_context; // init_python -void init_python(const char *path) { +void init_python(const char *program, const char *path) { + +// Py_NoSiteFlag = 1; +// Py_FrozenFlag = 1; +// Py_IgnoreEnvironmentFlag = 1; +// Py_IsolatedFlag = 1; append_inittab(); - Py_Initialize(); - - wchar_t *program = Py_DecodeLocale("clash", NULL); - if (program != NULL) { - Py_SetProgramName(program); - PyMem_RawFree(program); + wchar_t *programName = Py_DecodeLocale(program, NULL); + if (programName != NULL) { + Py_SetProgramName(programName); + PyMem_RawFree(programName); } // wchar_t *newPath = Py_DecodeLocale(path, NULL); // if (newPath != NULL) { // Py_SetPath(newPath); +// PyMem_RawFree(newPath); // } +// Py_Initialize(); + Py_InitializeEx(0); + char *pathPrefix = "import sys; sys.path.append('"; char *pathSuffix = "')"; char *newPath = (char *) malloc(strlen(pathPrefix) + strlen(path) + strlen(pathSuffix)); diff --git a/component/script/clash_module.go b/component/script/clash_module.go index 72806781..21ed551e 100644 --- a/component/script/clash_module.go +++ b/component/script/clash_module.go @@ -74,7 +74,7 @@ func (pyObject *PyObject) Clear() { } // Py_Initialize initialize Python3 -func Py_Initialize(path string) error { +func Py_Initialize(program string, path string) error { lock.Lock() defer lock.Unlock() @@ -89,8 +89,7 @@ func Py_Initialize(path string) error { cPath := C.CString(path) //defer C.free(unsafe.Pointer(cPath)) - C.init_python(cPath) - //C.Py_Initialize() + C.init_python(C.CString(program), cPath) err := PyLastError() if err != nil { @@ -129,17 +128,10 @@ func Py_Finalize() { } } +//Py_GetVersion get func Py_GetVersion() string { cversion := C.Py_GetVersion() - return C.GoString(cversion) -} - -func PyRun_SimpleString(command string) int { - ccommand := C.CString(command) - defer C.free(unsafe.Pointer(ccommand)) - - // C.PyRun_SimpleString is a macro, using C.PyRun_SimpleStringFlags instead - return int(C.PyRun_SimpleStringFlags(ccommand, nil)) + return strings.Split(C.GoString(cversion), "\n")[0] } // loadPyFunc loads a Python function by module and function name @@ -311,13 +303,19 @@ func initPython3Callback() { //NewClashPyContext new clash context for python func NewClashPyContext(ruleProvidersName []string) error { - cStringArr := make([]*C.char, len(ruleProvidersName)) + length := len(ruleProvidersName) + cStringArr := make([]*C.char, length) for i, v := range ruleProvidersName { cStringArr[i] = C.CString(v) defer C.free(unsafe.Pointer(cStringArr[i])) } - rs := int(C.new_clash_py_context((**C.char)(unsafe.Pointer(&cStringArr[0])), C.int(len(ruleProvidersName)))) + cArrPointer := unsafe.Pointer(nil) + if length > 0 { + cArrPointer = unsafe.Pointer(&cStringArr[0]) + } + + rs := int(C.new_clash_py_context((**C.char)(cArrPointer), C.int(length))) if rs == 0 { err := PyLastError() @@ -335,5 +333,5 @@ func killSelf() { return } - p.Signal(syscall.SIGINT) + _ = p.Signal(syscall.SIGINT) } diff --git a/component/script/clash_module.h b/component/script/clash_module.h index 9d815874..3e03e16d 100644 --- a/component/script/clash_module.h +++ b/component/script/clash_module.h @@ -29,7 +29,7 @@ void set_log_callback(log_callback cb); /*---------------------------------------------------------------*/ void append_inittab(); -void init_python(const char *path); +void init_python(const char *program, const char *path); void load_main_func(); void finalize_Python(); void py_clear(PyObject *obj); diff --git a/component/script/clash_module_export.go b/component/script/clash_module_export.go index 02fa27bf..b3f5355b 100644 --- a/component/script/clash_module_export.go +++ b/component/script/clash_module_export.go @@ -85,13 +85,25 @@ func ruleProviderCallbackFn(cProviderName *C.char, cMetadata *C.struct_Metadata) dstIp := C.GoString(cMetadata.dst_ip) dstPort := strconv.Itoa(int(cMetadata.dst_port)) + dst := net.ParseIP(dstIp) + addrType := constant.AtypDomainName + + if dst != nil { + if dst.To4() != nil { + addrType = constant.AtypIPv4 + } else { + addrType = constant.AtypIPv6 + } + } + metadata := &constant.Metadata{ - Process: processName, - SrcIP: net.ParseIP(srcIp), - DstIP: net.ParseIP(dstIp), - SrcPort: srcPort, - DstPort: dstPort, - Host: host, + Process: processName, + SrcIP: net.ParseIP(srcIp), + DstIP: dst, + SrcPort: srcPort, + DstPort: dstPort, + AddrType: addrType, + Host: host, } providerName := C.GoString(cProviderName) diff --git a/config/config.go b/config/config.go index 43b472d6..eed0b4d0 100644 --- a/config/config.go +++ b/config/config.go @@ -365,10 +365,10 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[ providersMap[name] = pd } - for _, provider := range providersMap { - log.Infoln("Start initial provider %s", provider.Name()) - if err := provider.Initial(); err != nil { - return nil, nil, fmt.Errorf("initial proxy provider %s error: %w", provider.Name(), err) + for _, rp := range providersMap { + log.Infoln("Start initial provider %s", rp.Name()) + if err := rp.Initial(); err != nil { + return nil, nil, fmt.Errorf("initial proxy provider %s error: %w", rp.Name(), err) } } @@ -474,7 +474,7 @@ time = ClashTime() return fmt.Errorf("initialized script module failure, %s", err.Error()) } - if err = S.Py_Initialize(C.Path.ScriptDir()); err != nil { + if err = S.Py_Initialize(C.Path.GetExecutableFullPath(), C.Path.ScriptDir()); err != nil { return fmt.Errorf("initialized script module failure, %s", err.Error()) } else if mode == T.Script { if err = S.LoadMainFunction(); err != nil { @@ -482,7 +482,7 @@ time = ClashTime() } } - log.Infoln("Start initial script module successful") + log.Infoln("Start initial script module successful, version: %s", S.Py_GetVersion()) return nil } @@ -561,7 +561,7 @@ func parseRules(cfg *RawConfig, proxies map[string]C.Proxy) ([]C.Rule, map[strin if err != nil { return nil, nil, err } else { - log.Infoln("Start initial script context successful") + log.Infoln("Start initial script context successful, provider records: %v", len(providerNames)) } } @@ -582,7 +582,7 @@ func parseHosts(cfg *RawConfig) (*trie.DomainTrie, error) { if ip == nil { return nil, fmt.Errorf("%s is not a valid IP", ipStr) } - tree.Insert(domain, ip) + _ = tree.Insert(domain, ip) } } @@ -740,7 +740,7 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie) (*DNS, error) { if len(cfg.FakeIPFilter) != 0 { host = trie.New() for _, domain := range cfg.FakeIPFilter { - host.Insert(domain, true) + _ = host.Insert(domain, true) } } diff --git a/constant/path.go b/constant/path.go index 83fad82d..f0f4e8c3 100644 --- a/constant/path.go +++ b/constant/path.go @@ -80,7 +80,7 @@ func (p *path) ScriptDir() string { p.scriptDir = dir } else { p.scriptDir = P.Join(os.TempDir(), Name) - os.MkdirAll(p.scriptDir, 0o644) + _ = os.MkdirAll(p.scriptDir, 0o644) } return p.scriptDir } @@ -92,3 +92,12 @@ func (p *path) Script() string { func (p *path) GetAssetLocation(file string) string { return P.Join(p.homeDir, file) } + +func (p *path) GetExecutableFullPath() string { + exePath, err := os.Executable() + if err != nil { + return "clash" + } + res, _ := filepath.EvalSymlinks(exePath) + return res +} diff --git a/listener/tun/ipstack/lwip/tcp.go b/listener/tun/ipstack/lwip/tcp.go index 9433c763..1c7cba9c 100644 --- a/listener/tun/ipstack/lwip/tcp.go +++ b/listener/tun/ipstack/lwip/tcp.go @@ -22,10 +22,7 @@ func NewTCPHandler(dnsIP net.IP, tcpIn chan<- C.ConnContext) golwip.TCPConnHandl func (h *tcpHandler) Handle(conn net.Conn, target *net.TCPAddr) error { if shouldHijackDns(h.dnsIP, target.IP, target.Port) { hijackTCPDns(conn) - - if log.Level() == log.DEBUG { - log.Debugln("[TUN] hijack dns tcp: %s:%d", target.IP.String(), target.Port) - } + log.Debugln("[TUN] hijack dns tcp: %s:%d", target.IP.String(), target.Port) return nil } @@ -36,22 +33,27 @@ func (h *tcpHandler) Handle(conn net.Conn, target *net.TCPAddr) error { src, _ := conn.LocalAddr().(*net.TCPAddr) dst, _ := conn.RemoteAddr().(*net.TCPAddr) - //addrType := C.AtypIPv4 - //if dst.IP.To4() == nil { - // addrType = C.AtypIPv6 - //} + + addrType := C.AtypIPv4 + if dst.IP.To4() == nil { + addrType = C.AtypIPv6 + } metadata := &C.Metadata{ - NetWork: C.TCP, - Type: C.TUN, - SrcIP: src.IP, - DstIP: dst.IP, - SrcPort: strconv.Itoa(src.Port), - DstPort: strconv.Itoa(dst.Port), - Host: "", + NetWork: C.TCP, + Type: C.TUN, + SrcIP: src.IP, + DstIP: dst.IP, + SrcPort: strconv.Itoa(src.Port), + DstPort: strconv.Itoa(dst.Port), + AddrType: addrType, + Host: "", } go func(conn net.Conn, metadata *C.Metadata) { + //if c, ok := conn.(*net.TCPConn); ok { + // c.SetKeepAlive(true) + //} h.tcpIn <- context.NewConnContext(conn, metadata) }(conn, metadata) diff --git a/listener/tun/ipstack/lwip/udp.go b/listener/tun/ipstack/lwip/udp.go index f3b3891d..5a2b9c58 100644 --- a/listener/tun/ipstack/lwip/udp.go +++ b/listener/tun/ipstack/lwip/udp.go @@ -46,17 +46,14 @@ func NewUDPHandler(dnsIP net.IP, udpIn chan<- *inbound.PacketAdapter) golwip.UDP return &udpHandler{dnsIP, udpIn} } -func (h *udpHandler) Connect(conn golwip.UDPConn, target *net.UDPAddr) error { +func (h *udpHandler) Connect(golwip.UDPConn, *net.UDPAddr) error { return nil } func (h *udpHandler) ReceiveTo(conn golwip.UDPConn, data []byte, addr *net.UDPAddr) error { if shouldHijackDns(h.dnsIP, addr.IP, addr.Port) { hijackUDPDns(conn, data, addr) - - if log.Level() == log.DEBUG { - log.Debugln("[TUN] hijack dns udp: %s:%d", addr.IP.String(), addr.Port) - } + log.Debugln("[TUN] hijack dns udp: %s:%d", addr.IP.String(), addr.Port) return nil } diff --git a/listener/tun/ipstack/system/tcp.go b/listener/tun/ipstack/system/tcp.go index a064066a..f52f7268 100644 --- a/listener/tun/ipstack/system/tcp.go +++ b/listener/tun/ipstack/system/tcp.go @@ -16,26 +16,31 @@ func handleTCP(conn net.Conn, endpoint *binding.Endpoint, tcpIn chan<- C.ConnCon Port: int(endpoint.Source.Port), Zone: "", } + dst := &net.TCPAddr{ IP: endpoint.Target.IP, Port: int(endpoint.Target.Port), Zone: "", } - //addrType := C.AtypIPv4 - //if dst.IP.To4() == nil { - // addrType = C.AtypIPv6 - //} - - metadata := &C.Metadata{ - NetWork: C.TCP, - Type: C.TUN, - SrcIP: src.IP, - DstIP: dst.IP, - SrcPort: strconv.Itoa(src.Port), - DstPort: strconv.Itoa(dst.Port), - Host: "", + addrType := C.AtypIPv4 + if dst.IP.To4() == nil { + addrType = C.AtypIPv6 } + metadata := &C.Metadata{ + NetWork: C.TCP, + Type: C.TUN, + SrcIP: src.IP, + DstIP: dst.IP, + SrcPort: strconv.Itoa(src.Port), + DstPort: strconv.Itoa(dst.Port), + AddrType: addrType, + Host: "", + } + + //if c, ok := conn.(*net.TCPConn); ok { + // c.SetKeepAlive(true) + //} tcpIn <- context.NewConnContext(conn, metadata) } diff --git a/listener/tun/ipstack/system/tun.go b/listener/tun/ipstack/system/tun.go index 0a3c3f72..fbfb8cb1 100644 --- a/listener/tun/ipstack/system/tun.go +++ b/listener/tun/ipstack/system/tun.go @@ -60,10 +60,7 @@ func NewAdapter(device dev.TunDevice, conf config.Tun, mtu int, gateway, mirror t.SetTCPHandler(func(conn net.Conn, endpoint *binding.Endpoint) { if shouldHijackDns(dnsAddr, endpoint.Target) { hijackTCPDns(conn) - - if log.Level() == log.DEBUG { - log.Debugln("[TUN] hijack dns tcp: %s:%d", endpoint.Target.IP.String(), endpoint.Target.Port) - } + log.Debugln("[TUN] hijack dns tcp: %s:%d", endpoint.Target.IP.String(), endpoint.Target.Port) return } @@ -72,10 +69,7 @@ func NewAdapter(device dev.TunDevice, conf config.Tun, mtu int, gateway, mirror t.SetUDPHandler(func(payload []byte, endpoint *binding.Endpoint, sender redirect.UDPSender) { if shouldHijackDns(dnsAddr, endpoint.Target) { hijackUDPDns(payload, endpoint, sender) - - if log.Level() == log.DEBUG { - log.Debugln("[TUN] hijack dns udp: %s:%d", endpoint.Target.IP.String(), endpoint.Target.Port) - } + log.Debugln("[TUN] hijack dns udp: %s:%d", endpoint.Target.IP.String(), endpoint.Target.Port) return }