From 9270d3c475b451115bb952547e698a6d314a24fb Mon Sep 17 00:00:00 2001 From: MetaCubeX Date: Sat, 19 Mar 2022 01:11:27 +0800 Subject: [PATCH] =?UTF-8?q?[=E5=86=85=E5=AE=B9]=201.autoIptables=20?= =?UTF-8?q?=E5=BC=80=E5=85=B3=202.go.mod=20=E8=B0=83=E6=95=B4=203.processN?= =?UTF-8?q?ame=20=E8=B0=83=E6=95=B4=204.makefile=20=E8=B0=83=E6=95=B4=205.?= =?UTF-8?q?Tun=E6=A8=A1=E5=9D=97=20=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/codeql-analysis.yml | 29 ---- .github/workflows/linter.yml | 27 ---- Makefile | 18 ++- component/process/process_android.go | 5 + go.mod | 6 +- go.sum | 6 +- hub/executor/executor.go | 23 +-- listener/listener.go | 5 +- listener/tun/device/tun/tun_windows.go | 2 +- listener/tun/device/tun/wintun/dll_windows.go | 94 +++++++++++ .../tun/wintun/embed_dll/windows_386.go | 21 +++ .../tun/wintun/embed_dll/windows_amd64.go | 21 +++ .../tun/wintun/embed_dll/windows_arm.go | 21 +++ .../tun/wintun/embed_dll/windows_arm64.go | 21 +++ listener/tun/device/tun/wintun/go.mod | 8 + listener/tun/device/tun/wintun/go.sum | 17 ++ .../tun/device/tun/wintun/package_info.go | 11 ++ .../tun/device/tun/wintun/session_windows.go | 90 +++++++++++ .../tun/device/tun/wintun/wintun_windows.go | 152 ++++++++++++++++++ listener/tun/tun_adapter.go | 12 +- 20 files changed, 502 insertions(+), 87 deletions(-) delete mode 100644 .github/workflows/codeql-analysis.yml delete mode 100644 .github/workflows/linter.yml create mode 100755 listener/tun/device/tun/wintun/dll_windows.go create mode 100755 listener/tun/device/tun/wintun/embed_dll/windows_386.go create mode 100755 listener/tun/device/tun/wintun/embed_dll/windows_amd64.go create mode 100755 listener/tun/device/tun/wintun/embed_dll/windows_arm.go create mode 100755 listener/tun/device/tun/wintun/embed_dll/windows_arm64.go create mode 100755 listener/tun/device/tun/wintun/go.mod create mode 100755 listener/tun/device/tun/wintun/go.sum create mode 100755 listener/tun/device/tun/wintun/package_info.go create mode 100755 listener/tun/device/tun/wintun/session_windows.go create mode 100755 listener/tun/device/tun/wintun/wintun_windows.go diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index fb1e7fd5..00000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: CodeQL - -on: - push: - branches: [ rm ] -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - language: ['go'] - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: ${{ matrix.language }} - - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml deleted file mode 100644 index f6b622f5..00000000 --- a/.github/workflows/linter.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Linter -on: [push, pull_request] -jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Get latest go version - id: version - run: | - echo ::set-output name=go_version::$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g') - - - name: Setup Go - uses: actions/setup-go@v2 - #with: - # go-version: ${{ steps.version.outputs.go_version }} - with: - go-version: 1.18.x - - - name: golangci-lint - #uses: golangci/golangci-lint-action@v3 - #with: - # version: latest - run: | - go install github.com/golangci/golangci-lint/cmd/golangci-lint@ec95236 - golangci-lint run ./... diff --git a/Makefile b/Makefile index d52c8df8..833b8ca4 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,9 @@ GOBUILD=CGO_ENABLED=0 go build -trimpath -ldflags '-X "github.com/Dreamacro/clas PLATFORM_LIST = \ darwin-amd64 \ darwin-arm64 \ - linux-amd64 \ + linux-amd64v1 \ + linux-amd64v2 \ + linux-amd64v3 \ linux-armv5 \ linux-armv6 \ linux-armv7 \ @@ -28,7 +30,7 @@ PLATFORM_LIST = \ WINDOWS_ARCH_LIST = \ windows-386 \ - windows-amd64 \ + windows-amd64v1 \ windows-amd64v2 \ windows-amd64v3 \ windows-arm64 \ @@ -50,9 +52,15 @@ darwin-arm64: linux-386: GOARCH=386 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ -linux-amd64: +linux-amd64v3: GOARCH=amd64 GOOS=linux GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ +linux-amd64v2: + GOARCH=amd64 GOOS=linux GOAMD64=v2 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ + +linux-amd64v1: + GOARCH=amd64 GOOS=linux GOAMD64=v1 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ + linux-arm64: GOARCH=arm64 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ @@ -104,8 +112,8 @@ windows-amd64v3: windows-amd64v2: GOARCH=amd64 GOOS=windows GOAMD64=v2 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe -windows-amd64: - GOARCH=amd64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe +windows-amd64v1: + GOARCH=amd64 GOOS=windows GOAMD64=v1 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe windows-arm64: GOARCH=arm64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe diff --git a/component/process/process_android.go b/component/process/process_android.go index 719b5176..1850e5f7 100644 --- a/component/process/process_android.go +++ b/component/process/process_android.go @@ -211,10 +211,15 @@ func resolveProcessNameByProcSearch(inode, uid int32) (string, error) { } 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])) } diff --git a/go.mod b/go.mod index 615e6d4f..b4928679 100644 --- a/go.mod +++ b/go.mod @@ -23,9 +23,9 @@ require ( golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd golang.org/x/net v0.0.0-20220225172249-27dd8689420f golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf + golang.org/x/sys v0.0.0-20220318055525-2edf467146b5 golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 - golang.zx2c4.com/wireguard v0.0.0-20220310012736-ae6bc4dd64e1 + golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6 golang.zx2c4.com/wireguard/windows v0.5.3 google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v2 v2.4.0 @@ -57,4 +57,4 @@ require ( ) -replace golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 => github.com/MetaCubeX/wintun-go v0.0.0-20220317182248-e32f9221663c +replace golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 => ./listener/tun/device/tun/wintun diff --git a/go.sum b/go.sum index cd1370ca..324a6cdb 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,6 @@ git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGy github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Dreamacro/go-shadowsocks2 v0.1.7 h1:8CtbE1HoPPMfrQZGXmlluq6dO2lL31W6WRRE8fabc4Q= github.com/Dreamacro/go-shadowsocks2 v0.1.7/go.mod h1:8p5G4cAj5ZlXwUR+Ww63gfSikr8kvw8uw3TDwLAJpUc= -github.com/MetaCubeX/wintun-go v0.0.0-20220317182248-e32f9221663c h1:fyg+AJU5BRmuEGeVexyABUiChIBeZ1UaER4DaV0jSLo= -github.com/MetaCubeX/wintun-go v0.0.0-20220317182248-e32f9221663c/go.mod h1:9ekUVS60VUdCP+s3E8TkAHmk04Wsu3DGU4Ruq8N7kaQ= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= @@ -309,6 +307,8 @@ golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf h1:Fm4IcnUL803i92qDlmB0obyHmosDrxZWxJL3gIeNqOw= golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220318055525-2edf467146b5 h1:saXMvIOKvRFwbOMicHXr0B1uwoxq9dGmLe5ExMES6c4= +golang.org/x/sys v0.0.0-20220318055525-2edf467146b5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -341,6 +341,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.zx2c4.com/wireguard v0.0.0-20220310012736-ae6bc4dd64e1 h1:iuQdvJn3LrXxz3Iony1qBGVS7kEy2uHYnnjHsVbzq/s= golang.zx2c4.com/wireguard v0.0.0-20220310012736-ae6bc4dd64e1/go.mod h1:TjUWrnD5ATh7bFvmm/ALEJZQ4ivKbETb6pmyj1vUoNI= +golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6 h1:kgBK1EGuTIYbwoKROmsoV0FQp08gnCcVa110A4Unqhk= +golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U= golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE= golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= diff --git a/hub/executor/executor.go b/hub/executor/executor.go index a8874ca8..086bfc72 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -78,12 +78,12 @@ func ApplyConfig(cfg *config.Config, force bool) { updateUsers(cfg.Users) updateHosts(cfg.Hosts) - updateGeneral(cfg.General, cfg.Tun, force) + updateGeneral(cfg.General, force) updateProxies(cfg.Proxies, cfg.Providers) updateRules(cfg.Rules, cfg.RuleProviders) - updateIPTables(cfg.DNS, cfg.General.TProxyPort, cfg.General.Interface, cfg.Tun.Enable) + updateIPTables(cfg.DNS, cfg.General, cfg.Tun) updateDNS(cfg.DNS, cfg.Tun) - updateTun(cfg.Tun, cfg.DNS.FakeIPRange.IPNet().String()) + updateTun(cfg.Tun) updateExperimental(cfg) loadProvider(cfg.RuleProviders, cfg.Providers) updateProfile(cfg) @@ -213,11 +213,11 @@ func loadProvider(ruleProviders map[string]*provider.RuleProvider, proxyProvider } } -func updateTun(tun *config.Tun, tunAddressPrefix string) { - P.ReCreateTun(tun, tunAddressPrefix, tunnel.TCPIn(), tunnel.UDPIn()) +func updateTun(tun *config.Tun) { + P.ReCreateTun(tun, tunnel.TCPIn(), tunnel.UDPIn()) } -func updateGeneral(general *config.General, Tun *config.Tun, force bool) { +func updateGeneral(general *config.General, force bool) { tunnel.SetMode(general.Mode) resolver.DisableIPv6 = !general.IPv6 adapter.UnifiedDelay.Store(general.UnifiedDelay) @@ -302,10 +302,10 @@ func patchSelectGroup(proxies map[string]C.Proxy) { } } -func updateIPTables(dns *config.DNS, tProxyPort int, interfaceName string, tunEnable bool) { +func updateIPTables(dns *config.DNS, general *config.General, tun *config.Tun) { tproxy.CleanUpTProxyLinuxIPTables() - if runtime.GOOS != "linux" || tProxyPort == 0 { + if runtime.GOOS != "linux" || general.TProxyPort == 0 { return } @@ -322,7 +322,7 @@ func updateIPTables(dns *config.DNS, tProxyPort int, interfaceName string, tunEn return } - if tunEnable { + if tun.Enable { err = fmt.Errorf("TUN device must be disabe") return } @@ -340,8 +340,9 @@ func updateIPTables(dns *config.DNS, tProxyPort int, interfaceName string, tunEn if dialer.DefaultRoutingMark.Load() == 0 { dialer.DefaultRoutingMark.Store(2158) } - - err = tproxy.SetTProxyLinuxIPTables(interfaceName, tProxyPort, dnsPort) + if general.AutoIptables { + err = tproxy.SetTProxyLinuxIPTables(general.Interface, general.TProxyPort, dnsPort) + } } func Cleanup() { diff --git a/listener/listener.go b/listener/listener.go index 6df92e2d..aae8a83b 100644 --- a/listener/listener.go +++ b/listener/listener.go @@ -310,7 +310,7 @@ func ReCreateMixed(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P log.Infoln("Mixed(http+socks) proxy listening at: %s", mixedListener.Address()) } -func ReCreateTun(tunConf *config.Tun, tunAddressPrefix string, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) { +func ReCreateTun(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) { tunMux.Lock() defer tunMux.Unlock() @@ -330,8 +330,7 @@ func ReCreateTun(tunConf *config.Tun, tunAddressPrefix string, tcpIn chan<- C.Co if !tunConf.Enable { return } - - tunStackListener, err = tun.New(tunConf, tunAddressPrefix, tcpIn, udpIn) + tunStackListener, err = tun.New(tunConf, tcpIn, udpIn) if err != nil { log.Warnln("Failed to start TUN interface: %s", err.Error()) } diff --git a/listener/tun/device/tun/tun_windows.go b/listener/tun/device/tun/tun_windows.go index 3f6eb444..29877440 100644 --- a/listener/tun/device/tun/tun_windows.go +++ b/listener/tun/device/tun/tun_windows.go @@ -8,7 +8,7 @@ import ( func init() { guid, _ := windows.GUIDFromString("{330EAEF8-7578-5DF2-D97B-8DADC0EA85CB}") - tun.WintunTunnelType = "Clash" + tun.WintunTunnelType = "Meta" tun.WintunStaticRequestedGUID = &guid } diff --git a/listener/tun/device/tun/wintun/dll_windows.go b/listener/tun/device/tun/wintun/dll_windows.go new file mode 100755 index 00000000..4368100b --- /dev/null +++ b/listener/tun/device/tun/wintun/dll_windows.go @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved. + */ + +package wintun + +import ( + "fmt" + "golang.zx2c4.com/wintun/embed_dll" + "golang.zx2c4.com/wireguard/windows/driver/memmod" + "sync" + "sync/atomic" + "unsafe" +) + +func newLazyDLL(name string, onLoad func(d *lazyDLL)) *lazyDLL { + return &lazyDLL{Name: name, onLoad: onLoad} +} + +func (d *lazyDLL) NewProc(name string) *lazyProc { + return &lazyProc{dll: d, Name: name} +} + +type lazyProc struct { + Name string + mu sync.Mutex + dll *lazyDLL + addr uintptr +} + +func (p *lazyProc) Find() error { + if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr))) != nil { + return nil + } + p.mu.Lock() + defer p.mu.Unlock() + if p.addr != 0 { + return nil + } + + err := p.dll.Load() + if err != nil { + return fmt.Errorf("Error loading %v DLL: %w", p.dll.Name, err) + } + addr, err := p.nameToAddr() + if err != nil { + return fmt.Errorf("Error getting %v address: %w", p.Name, err) + } + + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr)), unsafe.Pointer(addr)) + return nil +} + +func (p *lazyProc) Addr() uintptr { + err := p.Find() + if err != nil { + panic(err) + } + return p.addr +} + +type lazyDLL struct { + Name string + mu sync.Mutex + module *memmod.Module + onLoad func(d *lazyDLL) +} + +func (d *lazyDLL) Load() error { + if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.module))) != nil { + return nil + } + d.mu.Lock() + defer d.mu.Unlock() + if d.module != nil { + return nil + } + + module, err := memmod.LoadLibrary(embed_dll.DDlContent) + if err != nil { + return fmt.Errorf("unable to load library: %w", err) + } + + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.module)), unsafe.Pointer(module)) + if d.onLoad != nil { + d.onLoad(d) + } + return nil +} + +func (p *lazyProc) nameToAddr() (uintptr, error) { + return p.dll.module.ProcAddressByName(p.Name) +} diff --git a/listener/tun/device/tun/wintun/embed_dll/windows_386.go b/listener/tun/device/tun/wintun/embed_dll/windows_386.go new file mode 100755 index 00000000..05fab743 --- /dev/null +++ b/listener/tun/device/tun/wintun/embed_dll/windows_386.go @@ -0,0 +1,21 @@ +package embed_dll + +// Copyright 2020 MeshStep Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +import ( + _ "embed" +) + +//go:embed x86/wintun.dll +var DDlContent []byte diff --git a/listener/tun/device/tun/wintun/embed_dll/windows_amd64.go b/listener/tun/device/tun/wintun/embed_dll/windows_amd64.go new file mode 100755 index 00000000..2ee9f791 --- /dev/null +++ b/listener/tun/device/tun/wintun/embed_dll/windows_amd64.go @@ -0,0 +1,21 @@ +package embed_dll + +// Copyright 2020 MeshStep Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +import ( + _ "embed" +) + +//go:embed amd64/wintun.dll +var DDlContent []byte diff --git a/listener/tun/device/tun/wintun/embed_dll/windows_arm.go b/listener/tun/device/tun/wintun/embed_dll/windows_arm.go new file mode 100755 index 00000000..0636f21b --- /dev/null +++ b/listener/tun/device/tun/wintun/embed_dll/windows_arm.go @@ -0,0 +1,21 @@ +package embed_dll + +// Copyright 2020 MeshStep Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +import ( + _ "embed" +) + +//go:embed arm/wintun.dll +var DDlContent []byte diff --git a/listener/tun/device/tun/wintun/embed_dll/windows_arm64.go b/listener/tun/device/tun/wintun/embed_dll/windows_arm64.go new file mode 100755 index 00000000..1e5d605d --- /dev/null +++ b/listener/tun/device/tun/wintun/embed_dll/windows_arm64.go @@ -0,0 +1,21 @@ +package embed_dll + +// Copyright 2020 MeshStep Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +import ( + _ "embed" +) + +//go:embed arm64/wintun.dll +var DDlContent []byte diff --git a/listener/tun/device/tun/wintun/go.mod b/listener/tun/device/tun/wintun/go.mod new file mode 100755 index 00000000..33d4b961 --- /dev/null +++ b/listener/tun/device/tun/wintun/go.mod @@ -0,0 +1,8 @@ +module golang.zx2c4.com/wintun + +go 1.18 + +require ( + golang.org/x/sys v0.0.0-20220318055525-2edf467146b5 + golang.zx2c4.com/wireguard/windows v0.5.3 +) diff --git a/listener/tun/device/tun/wintun/go.sum b/listener/tun/device/tun/wintun/go.sum new file mode 100755 index 00000000..e1f1e5ec --- /dev/null +++ b/listener/tun/device/tun/wintun/go.sum @@ -0,0 +1,17 @@ +github.com/MetaCubeX/Clash.Meta v1.9.1 h1:jHZhVRBxFuaCRBN9vxB/FL5R16wY4kIgNqjszdXPeLs= +github.com/MetaCubeX/Clash.Meta v1.9.1/go.mod h1:/I4cSh+PcgmtS5SEnFp8RANL6aVRd3i9YOult+mKLhU= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf h1:Fm4IcnUL803i92qDlmB0obyHmosDrxZWxJL3gIeNqOw= +golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE= +golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/listener/tun/device/tun/wintun/package_info.go b/listener/tun/device/tun/wintun/package_info.go new file mode 100755 index 00000000..22e9bd05 --- /dev/null +++ b/listener/tun/device/tun/wintun/package_info.go @@ -0,0 +1,11 @@ +//go:build windows +// +build windows + +// Modified from: https://git.zx2c4.com/wireguard-go/tree/tun/wintun + +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved. + */ + +package wintun diff --git a/listener/tun/device/tun/wintun/session_windows.go b/listener/tun/device/tun/wintun/session_windows.go new file mode 100755 index 00000000..f023baf7 --- /dev/null +++ b/listener/tun/device/tun/wintun/session_windows.go @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved. + */ + +package wintun + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +type Session struct { + handle uintptr +} + +const ( + PacketSizeMax = 0xffff // Maximum packet size + RingCapacityMin = 0x20000 // Minimum ring capacity (128 kiB) + RingCapacityMax = 0x4000000 // Maximum ring capacity (64 MiB) +) + +// Packet with data +type Packet struct { + Next *Packet // Pointer to next packet in queue + Size uint32 // Size of packet (max WINTUN_MAX_IP_PACKET_SIZE) + Data *[PacketSizeMax]byte // Pointer to layer 3 IPv4 or IPv6 packet +} + +var ( + procWintunAllocateSendPacket = modwintun.NewProc("WintunAllocateSendPacket") + procWintunEndSession = modwintun.NewProc("WintunEndSession") + procWintunGetReadWaitEvent = modwintun.NewProc("WintunGetReadWaitEvent") + procWintunReceivePacket = modwintun.NewProc("WintunReceivePacket") + procWintunReleaseReceivePacket = modwintun.NewProc("WintunReleaseReceivePacket") + procWintunSendPacket = modwintun.NewProc("WintunSendPacket") + procWintunStartSession = modwintun.NewProc("WintunStartSession") +) + +func (wintun *Adapter) StartSession(capacity uint32) (session Session, err error) { + r0, _, e1 := syscall.Syscall(procWintunStartSession.Addr(), 2, uintptr(wintun.handle), uintptr(capacity), 0) + if r0 == 0 { + err = e1 + } else { + session = Session{r0} + } + return +} + +func (session Session) End() { + syscall.Syscall(procWintunEndSession.Addr(), 1, session.handle, 0, 0) + session.handle = 0 +} + +func (session Session) ReadWaitEvent() (handle windows.Handle) { + r0, _, _ := syscall.Syscall(procWintunGetReadWaitEvent.Addr(), 1, session.handle, 0, 0) + handle = windows.Handle(r0) + return +} + +func (session Session) ReceivePacket() (packet []byte, err error) { + var packetSize uint32 + r0, _, e1 := syscall.Syscall(procWintunReceivePacket.Addr(), 2, session.handle, uintptr(unsafe.Pointer(&packetSize)), 0) + if r0 == 0 { + err = e1 + return + } + packet = unsafe.Slice((*byte)(unsafe.Pointer(r0)), packetSize) + return +} + +func (session Session) ReleaseReceivePacket(packet []byte) { + syscall.Syscall(procWintunReleaseReceivePacket.Addr(), 2, session.handle, uintptr(unsafe.Pointer(&packet[0])), 0) +} + +func (session Session) AllocateSendPacket(packetSize int) (packet []byte, err error) { + r0, _, e1 := syscall.Syscall(procWintunAllocateSendPacket.Addr(), 2, session.handle, uintptr(packetSize), 0) + if r0 == 0 { + err = e1 + return + } + packet = unsafe.Slice((*byte)(unsafe.Pointer(r0)), packetSize) + return +} + +func (session Session) SendPacket(packet []byte) { + syscall.Syscall(procWintunSendPacket.Addr(), 2, session.handle, uintptr(unsafe.Pointer(&packet[0])), 0) +} diff --git a/listener/tun/device/tun/wintun/wintun_windows.go b/listener/tun/device/tun/wintun/wintun_windows.go new file mode 100755 index 00000000..254dc1e8 --- /dev/null +++ b/listener/tun/device/tun/wintun/wintun_windows.go @@ -0,0 +1,152 @@ +//go:build windows + +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved. + */ + +package wintun + +import ( + "log" + "runtime" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +type loggerLevel int + +const ( + logInfo loggerLevel = iota + logWarn + logErr +) + +const AdapterNameMax = 128 + +type Adapter struct { + handle uintptr +} + +var ( + modwintun = newLazyDLL("wintun.dll", setupLogger) + procWintunCreateAdapter = modwintun.NewProc("WintunCreateAdapter") + procWintunOpenAdapter = modwintun.NewProc("WintunOpenAdapter") + procWintunCloseAdapter = modwintun.NewProc("WintunCloseAdapter") + procWintunDeleteDriver = modwintun.NewProc("WintunDeleteDriver") + procWintunGetAdapterLUID = modwintun.NewProc("WintunGetAdapterLUID") + procWintunGetRunningDriverVersion = modwintun.NewProc("WintunGetRunningDriverVersion") +) + +type TimestampedWriter interface { + WriteWithTimestamp(p []byte, ts int64) (n int, err error) +} + +func logMessage(level loggerLevel, timestamp uint64, msg *uint16) int { + if tw, ok := log.Default().Writer().(TimestampedWriter); ok { + tw.WriteWithTimestamp([]byte(log.Default().Prefix()+windows.UTF16PtrToString(msg)), (int64(timestamp)-116444736000000000)*100) + } else { + log.Println(windows.UTF16PtrToString(msg)) + } + return 0 +} + +func setupLogger(dll *lazyDLL) { + var callback uintptr + if runtime.GOARCH == "386" { + callback = windows.NewCallback(func(level loggerLevel, timestampLow, timestampHigh uint32, msg *uint16) int { + return logMessage(level, uint64(timestampHigh)<<32|uint64(timestampLow), msg) + }) + } else if runtime.GOARCH == "arm" { + callback = windows.NewCallback(func(level loggerLevel, _, timestampLow, timestampHigh uint32, msg *uint16) int { + return logMessage(level, uint64(timestampHigh)<<32|uint64(timestampLow), msg) + }) + } else if runtime.GOARCH == "amd64" || runtime.GOARCH == "arm64" { + callback = windows.NewCallback(logMessage) + } + syscall.Syscall(dll.NewProc("WintunSetLogger").Addr(), 1, callback, 0, 0) +} + +func closeAdapter(wintun *Adapter) { + syscall.Syscall(procWintunCloseAdapter.Addr(), 1, wintun.handle, 0, 0) +} + +// CreateAdapter creates a Wintun adapter. name is the cosmetic name of the adapter. +// tunnelType represents the type of adapter and should be "Wintun". requestedGUID is +// the GUID of the created network adapter, which then influences NLA generation +// deterministically. If it is set to nil, the GUID is chosen by the system at random, +// and hence a new NLA entry is created for each new adapter. +func CreateAdapter(name string, tunnelType string, requestedGUID *windows.GUID) (wintun *Adapter, err error) { + var name16 *uint16 + name16, err = windows.UTF16PtrFromString(name) + if err != nil { + return + } + var tunnelType16 *uint16 + tunnelType16, err = windows.UTF16PtrFromString(tunnelType) + if err != nil { + return + } + r0, _, e1 := syscall.Syscall(procWintunCreateAdapter.Addr(), 3, uintptr(unsafe.Pointer(name16)), uintptr(unsafe.Pointer(tunnelType16)), uintptr(unsafe.Pointer(requestedGUID))) + if r0 == 0 { + err = e1 + return + } + wintun = &Adapter{handle: r0} + runtime.SetFinalizer(wintun, closeAdapter) + return +} + +// OpenAdapter opens an existing Wintun adapter by name. +func OpenAdapter(name string) (wintun *Adapter, err error) { + var name16 *uint16 + name16, err = windows.UTF16PtrFromString(name) + if err != nil { + return + } + r0, _, e1 := syscall.Syscall(procWintunOpenAdapter.Addr(), 1, uintptr(unsafe.Pointer(name16)), 0, 0) + if r0 == 0 { + err = e1 + return + } + wintun = &Adapter{handle: r0} + runtime.SetFinalizer(wintun, closeAdapter) + return +} + +// Close closes a Wintun adapter. +func (wintun *Adapter) Close() (err error) { + runtime.SetFinalizer(wintun, nil) + r1, _, e1 := syscall.Syscall(procWintunCloseAdapter.Addr(), 1, wintun.handle, 0, 0) + if r1 == 0 { + err = e1 + } + return +} + +// Uninstall removes the driver from the system if no drivers are currently in use. +func Uninstall() (err error) { + r1, _, e1 := syscall.Syscall(procWintunDeleteDriver.Addr(), 0, 0, 0, 0) + if r1 == 0 { + err = e1 + } + return +} + +// RunningVersion returns the version of the loaded driver. +func RunningVersion() (version uint32, err error) { + r0, _, e1 := syscall.Syscall(procWintunGetRunningDriverVersion.Addr(), 0, 0, 0, 0) + version = uint32(r0) + if version == 0 { + err = e1 + } + return +} + +// LUID returns the LUID of the adapter. +func (wintun *Adapter) LUID() (luid uint64) { + syscall.Syscall(procWintunGetAdapterLUID.Addr(), 2, uintptr(wintun.handle), uintptr(unsafe.Pointer(&luid)), 0) + return +} diff --git a/listener/tun/tun_adapter.go b/listener/tun/tun_adapter.go index f30456f5..a54087be 100644 --- a/listener/tun/tun_adapter.go +++ b/listener/tun/tun_adapter.go @@ -24,9 +24,9 @@ import ( ) // New TunAdapter -func New(tunConf *config.Tun, tunAddressPrefix string, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) (ipstack.Stack, error) { +func New(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) (ipstack.Stack, error) { var ( - tunAddress = netip.MustParsePrefix(tunAddressPrefix) + tunAddress = netip.MustParsePrefix("198.18.0.1/16") devName = tunConf.Device stackType = tunConf.Stack autoRoute = tunConf.AutoRoute @@ -42,9 +42,9 @@ func New(tunConf *config.Tun, tunAddressPrefix string, tcpIn chan<- C.ConnContex devName = generateDeviceName() } - if !tunAddress.IsValid() || !tunAddress.Addr().Is4() { - tunAddress = netip.MustParsePrefix("198.18.0.1/16") - } + //if !tunAddress.IsValid() || !tunAddress.Addr().Is4() { + // tunAddress = netip.MustParsePrefix("198.18.0.1/16") + //} process.AppendLocalIPs(tunAddress.Masked().Addr().Next().AsSlice()) @@ -116,7 +116,7 @@ func New(tunConf *config.Tun, tunAddressPrefix string, tcpIn chan<- C.ConnContex func generateDeviceName() string { switch runtime.GOOS { case "darwin": - return tun.Driver + "://Meta" + return tun.Driver + "://utun" case "windows": return tun.Driver + "://Meta" default: