Feature: make wintun driver embed
This commit is contained in:
parent
b37e1fb2b9
commit
67905bcf7e
@ -150,7 +150,6 @@ Then manually create the default route and DNS server. If your device already ha
|
|||||||
Enjoy! :)
|
Enjoy! :)
|
||||||
|
|
||||||
#### For Windows:
|
#### For Windows:
|
||||||
go to [https://www.wintun.net](https://www.wintun.net) and download the latest release, copy the right `wintun.dll` into the system32 directory.
|
|
||||||
```yaml
|
```yaml
|
||||||
tun:
|
tun:
|
||||||
enable: true
|
enable: true
|
||||||
|
BIN
listener/tun/device/tun/driver/amd64/wintun.dll
Executable file
BIN
listener/tun/device/tun/driver/amd64/wintun.dll
Executable file
Binary file not shown.
BIN
listener/tun/device/tun/driver/arm/wintun.dll
Executable file
BIN
listener/tun/device/tun/driver/arm/wintun.dll
Executable file
Binary file not shown.
BIN
listener/tun/device/tun/driver/arm64/wintun.dll
Executable file
BIN
listener/tun/device/tun/driver/arm64/wintun.dll
Executable file
Binary file not shown.
233
listener/tun/device/tun/driver/dll_windows.go
Normal file
233
listener/tun/device/tun/driver/dll_windows.go
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/log"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
"golang.zx2c4.com/wireguard/windows/driver/memmod"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname modwintun golang.zx2c4.com/wintun.modwintun
|
||||||
|
|
||||||
|
//go:linkname procWintunCreateAdapter golang.zx2c4.com/wintun.procWintunCreateAdapter
|
||||||
|
|
||||||
|
//go:linkname procWintunOpenAdapter golang.zx2c4.com/wintun.procWintunOpenAdapter
|
||||||
|
|
||||||
|
//go:linkname procWintunCloseAdapter golang.zx2c4.com/wintun.procWintunCloseAdapter
|
||||||
|
|
||||||
|
//go:linkname procWintunDeleteDriver golang.zx2c4.com/wintun.procWintunDeleteDriver
|
||||||
|
|
||||||
|
//go:linkname procWintunGetAdapterLUID golang.zx2c4.com/wintun.procWintunGetAdapterLUID
|
||||||
|
|
||||||
|
//go:linkname procWintunGetRunningDriverVersion golang.zx2c4.com/wintun.procWintunGetRunningDriverVersion
|
||||||
|
|
||||||
|
//go:linkname procWintunAllocateSendPacket golang.zx2c4.com/wintun.procWintunAllocateSendPacket
|
||||||
|
|
||||||
|
//go:linkname procWintunEndSession golang.zx2c4.com/wintun.procWintunEndSession
|
||||||
|
|
||||||
|
//go:linkname procWintunGetReadWaitEvent golang.zx2c4.com/wintun.procWintunGetReadWaitEvent
|
||||||
|
|
||||||
|
//go:linkname procWintunReceivePacket golang.zx2c4.com/wintun.procWintunReceivePacket
|
||||||
|
|
||||||
|
//go:linkname procWintunReleaseReceivePacket golang.zx2c4.com/wintun.procWintunReleaseReceivePacket
|
||||||
|
|
||||||
|
//go:linkname procWintunSendPacket golang.zx2c4.com/wintun.procWintunSendPacket
|
||||||
|
|
||||||
|
//go:linkname procWintunStartSession golang.zx2c4.com/wintun.procWintunStartSession
|
||||||
|
|
||||||
|
var (
|
||||||
|
modwintun *lazyDLL
|
||||||
|
procWintunCreateAdapter *lazyProc
|
||||||
|
procWintunOpenAdapter *lazyProc
|
||||||
|
procWintunCloseAdapter *lazyProc
|
||||||
|
procWintunDeleteDriver *lazyProc
|
||||||
|
procWintunGetAdapterLUID *lazyProc
|
||||||
|
procWintunGetRunningDriverVersion *lazyProc
|
||||||
|
procWintunAllocateSendPacket *lazyProc
|
||||||
|
procWintunEndSession *lazyProc
|
||||||
|
procWintunGetReadWaitEvent *lazyProc
|
||||||
|
procWintunReceivePacket *lazyProc
|
||||||
|
procWintunReleaseReceivePacket *lazyProc
|
||||||
|
procWintunSendPacket *lazyProc
|
||||||
|
procWintunStartSession *lazyProc
|
||||||
|
)
|
||||||
|
|
||||||
|
type loggerLevel int
|
||||||
|
|
||||||
|
const (
|
||||||
|
logInfo loggerLevel = iota
|
||||||
|
logWarn
|
||||||
|
logErr
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
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")
|
||||||
|
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 InitWintun() (err error) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
err = fmt.Errorf("init wintun.dll error: %v", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err = modwintun.Load(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
procWintunCreateAdapter.Addr()
|
||||||
|
procWintunOpenAdapter.Addr()
|
||||||
|
procWintunCloseAdapter.Addr()
|
||||||
|
procWintunDeleteDriver.Addr()
|
||||||
|
procWintunGetAdapterLUID.Addr()
|
||||||
|
procWintunGetRunningDriverVersion.Addr()
|
||||||
|
procWintunAllocateSendPacket.Addr()
|
||||||
|
procWintunEndSession.Addr()
|
||||||
|
procWintunGetReadWaitEvent.Addr()
|
||||||
|
procWintunReceivePacket.Addr()
|
||||||
|
procWintunReleaseReceivePacket.Addr()
|
||||||
|
procWintunSendPacket.Addr()
|
||||||
|
procWintunStartSession.Addr()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLazyDLL(name string, onLoad func(d *lazyDLL)) *lazyDLL {
|
||||||
|
return &lazyDLL{Name: name, onLoad: onLoad}
|
||||||
|
}
|
||||||
|
|
||||||
|
func logMessage(level loggerLevel, _ uint64, msg *uint16) int {
|
||||||
|
switch level {
|
||||||
|
case logInfo:
|
||||||
|
log.Infoln("[TUN] %s", windows.UTF16PtrToString(msg))
|
||||||
|
case logWarn:
|
||||||
|
log.Warnln("[TUN] %s", windows.UTF16PtrToString(msg))
|
||||||
|
case logErr:
|
||||||
|
log.Errorln("[TUN] %s", windows.UTF16PtrToString(msg))
|
||||||
|
default:
|
||||||
|
log.Debugln("[TUN] %s", windows.UTF16PtrToString(msg))
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupLogger(dll *lazyDLL) {
|
||||||
|
var callback uintptr
|
||||||
|
if runtime.GOARCH == "386" {
|
||||||
|
callback = windows.NewCallback(func(level loggerLevel, _, _ uint32, msg *uint16) int {
|
||||||
|
return logMessage(level, 0, msg)
|
||||||
|
})
|
||||||
|
} else if runtime.GOARCH == "arm" {
|
||||||
|
callback = windows.NewCallback(func(level loggerLevel, _, _, _ uint32, msg *uint16) int {
|
||||||
|
return logMessage(level, 0, msg)
|
||||||
|
})
|
||||||
|
} else if runtime.GOARCH == "amd64" || runtime.GOARCH == "arm64" {
|
||||||
|
callback = windows.NewCallback(logMessage)
|
||||||
|
}
|
||||||
|
_, _, _ = syscall.SyscallN(dll.NewProc("WintunSetLogger").Addr(), callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 DLL: %s, MODULE: %s, error: %w", p.dll.Name, p.Name, err)
|
||||||
|
}
|
||||||
|
addr, err := p.nameToAddr()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error getting %s 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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *lazyProc) Load() error {
|
||||||
|
return p.dll.Load()
|
||||||
|
}
|
||||||
|
|
||||||
|
type lazyDLL struct {
|
||||||
|
Name string
|
||||||
|
Base windows.Handle
|
||||||
|
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(dllData)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to load library: %w", err)
|
||||||
|
}
|
||||||
|
d.Base = windows.Handle(module.BaseAddr())
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
13
listener/tun/device/tun/driver/dll_windows_386.go
Normal file
13
listener/tun/device/tun/driver/dll_windows_386.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed x86/wintun.dll
|
||||||
|
var dllData []byte
|
13
listener/tun/device/tun/driver/dll_windows_amd64.go
Normal file
13
listener/tun/device/tun/driver/dll_windows_amd64.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed amd64/wintun.dll
|
||||||
|
var dllData []byte
|
13
listener/tun/device/tun/driver/dll_windows_arm.go
Normal file
13
listener/tun/device/tun/driver/dll_windows_arm.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed arm/wintun.dll
|
||||||
|
var dllData []byte
|
13
listener/tun/device/tun/driver/dll_windows_arm64.go
Normal file
13
listener/tun/device/tun/driver/dll_windows_arm64.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed arm64/wintun.dll
|
||||||
|
var dllData []byte
|
10
listener/tun/device/tun/driver/package_info.go
Normal file
10
listener/tun/device/tun/driver/package_info.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
// https://git.zx2c4.com/wireguard-go/tree/tun/wintun
|
||||||
|
|
||||||
|
/* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package driver
|
BIN
listener/tun/device/tun/driver/x86/wintun.dll
Executable file
BIN
listener/tun/device/tun/driver/x86/wintun.dll
Executable file
Binary file not shown.
@ -3,7 +3,6 @@
|
|||||||
package tun
|
package tun
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -43,11 +42,11 @@ func Open(name string, mtu uint32) (_ device.Device, err error) {
|
|||||||
forcedMTU = int(t.mtu)
|
forcedMTU = int(t.mtu)
|
||||||
}
|
}
|
||||||
|
|
||||||
nt, err := tun.CreateTUN(t.name, forcedMTU) // forcedMTU do not work on wintun, need to be setting by other way
|
nt, err := newDevice(t.name, forcedMTU) // forcedMTU do not work on wintun, need to be setting by other way
|
||||||
|
|
||||||
// retry if abnormal exit on Windows at last time
|
// retry if abnormal exit at last time on Windows
|
||||||
if err != nil && runtime.GOOS == "windows" && errors.Is(err, os.ErrExist) {
|
if err != nil && runtime.GOOS == "windows" && os.IsExist(err) {
|
||||||
nt, err = tun.CreateTUN(t.name, forcedMTU)
|
nt, err = newDevice(t.name, forcedMTU)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -2,7 +2,13 @@
|
|||||||
|
|
||||||
package tun
|
package tun
|
||||||
|
|
||||||
|
import "golang.zx2c4.com/wireguard/tun"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
offset = 4 /* 4 bytes TUN_PI */
|
offset = 4 /* 4 bytes TUN_PI */
|
||||||
defaultMTU = 1500
|
defaultMTU = 1500
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func newDevice(name string, mtu int) (tun.Device, error) {
|
||||||
|
return tun.CreateTUN(name, mtu)
|
||||||
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package tun
|
package tun
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/Dreamacro/clash/listener/tun/device/tun/driver"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
"golang.zx2c4.com/wireguard/tun"
|
"golang.zx2c4.com/wireguard/tun"
|
||||||
)
|
)
|
||||||
@ -20,3 +22,11 @@ func init() {
|
|||||||
func (t *TUN) LUID() uint64 {
|
func (t *TUN) LUID() uint64 {
|
||||||
return t.nt.LUID()
|
return t.nt.LUID()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newDevice(name string, mtu int) (nt tun.Device, err error) {
|
||||||
|
if err = driver.InitWintun(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return tun.CreateTUN(name, mtu)
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user