This commit is contained in:
Michael Quigley
2020-04-08 12:12:21 -04:00
parent c6efa3b2ce
commit 4fab754dfb
2 changed files with 177 additions and 335 deletions
+162 -322
View File
@@ -1,328 +1,168 @@
package main
import (
"bufio"
"fmt"
"log"
"strings"
"wintun-testing/wireguard"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/mgr"
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/ipc"
"golang.zx2c4.com/wireguard/tun"
"golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/elevate"
"golang.zx2c4.com/wireguard/windows/ringlogger"
"golang.zx2c4.com/wireguard/windows/services"
"golang.zx2c4.com/wireguard/windows/version"
"bufio"
"fmt"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/mgr"
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/ipc"
"golang.zx2c4.com/wireguard/tun"
"golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/elevate"
"golang.zx2c4.com/wireguard/windows/ringlogger"
"golang.zx2c4.com/wireguard/windows/services"
"golang.zx2c4.com/wireguard/windows/version"
"log"
"os"
"strings"
"wintun-testing/wireguard"
)
const (
ExitSetupSuccess = 0
ExitSetupFailed = 1
)
func main(){
var r <-chan svc.ChangeRequest
var changes chan<- svc.Status
confPath := "c:\\git\\github\\ziti-windows-uwp\\wintun-testing\\simple.conf"
interfaceName := "ZitiTUN"
serviceError := services.ErrorSuccess
conf, err := conf.LoadFromPath(confPath)
if err != nil {
serviceError = services.ErrorLoadConfiguration
return
}
conf.DeduplicateNetworkEntries()
logPrefix := fmt.Sprintf("[%s] ", conf.Name)
log.SetPrefix(logPrefix)
log.Println("Starting", version.UserAgent())
if m, err := mgr.Connect(); err == nil {
if lockStatus, err := m.LockStatus(); err == nil && lockStatus.IsLocked {
/* If we don't do this, then the Wintun installation will block forever, because
* installing a Wintun device starts a service too. Apparently at boot time, Windows
* 8.1 locks the SCM for each service start, creating a deadlock if we don't announce
* that we're running before starting additional services.
*/
log.Printf("SCM locked for %v by %s, marking service as started", lockStatus.Age, lockStatus.Owner)
changes <- svc.Status{State: svc.Running}
}
m.Disconnect()
}
if serviceError != services.ErrorSuccess {
panic(serviceError)
}
var watcher *wireguard.InterfaceWatcher
log.Println("Watching network interfaces")
watcher, err = wireguard.WatchInterface()
if err != nil {
serviceError = services.ErrorSetNetConfig
return
}
log.Println("Resolving DNS names")
uapiConf, err := conf.ToUAPI()
if err != nil {
serviceError = services.ErrorDNSLookup
return
}
log.Println("Creating Wintun interface")
tunDevice, err := tun.CreateTUN(interfaceName, 0)
defer tunDevice.Close()
if err != nil {
serviceError = services.ErrorCreateWintun
return
}
nativeTun := tunDevice.(*tun.NativeTun)
wintunVersion, ndisVersion, err := nativeTun.Version()
if err != nil {
log.Printf("Warning: unable to determine Wintun version: %v", err)
} else {
log.Printf("Using Wintun/%s (NDIS %s)", wintunVersion, ndisVersion)
}
log.Println("Enabling firewall rules")
err = wireguard.EnableFirewall(conf, nativeTun)
if err != nil {
log.Printf("ERROR: %v", err)
serviceError = services.ErrorFirewall
return
}
log.Println("Enabling firewall rules")
err = wireguard.EnableFirewall(conf, nativeTun)
if err != nil {
serviceError = services.ErrorFirewall
return
}
log.Println("Dropping privileges")
err = elevate.DropAllPrivileges(true)
if err != nil {
serviceError = services.ErrorDropPrivileges
return
}
log.Println("Creating interface instance")
logOutput := log.New(ringlogger.Global, logPrefix, 0)
logger := &device.Logger{logOutput, logOutput, logOutput}
dev := device.NewDevice(tunDevice, logger)
log.Println("Setting interface configuration")
uapi, err := ipc.UAPIListen(conf.Name)
if err != nil {
serviceError = services.ErrorUAPIListen
return
}
ipcErr := dev.IpcSetOperation(bufio.NewReader(strings.NewReader(uapiConf)))
if ipcErr != nil {
err = ipcErr
serviceError = services.ErrorDeviceSetConfig
return
}
log.Println("Bringing peers up")
dev.Up()
watcher.Configure(dev, conf, nativeTun)
log.Println("Listening for UAPI requests")
go func() {
for {
conn, err := uapi.Accept()
if err != nil {
continue
}
go dev.IpcHandle(conn)
}
}()
changes <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop | svc.AcceptShutdown}
log.Println("Startup complete")
for {
select {
case c := <-r:
switch c.Cmd {
case svc.Stop, svc.Shutdown:
return
case svc.Interrogate:
changes <- c.CurrentStatus
default:
log.Printf("Unexpected service control request #%d\n", c)
}
case <-dev.Wait():
return
case e := <-watcher.Errors:
serviceError, err = e.ServiceError, e.Err
return
}
}
/*
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
"golang.zx2c4.com/wireguard/windows/version"
"log"
"net"
"os"
"os/signal"
user2 "os/user"
"strings"
"sync"
"syscall"
fmt.Printf("bootstrapped conf: %v", serviceName)
user,err := user2.Current()
fmt.Printf("Hi there: %v", user)
if len(os.Args) != 2 {
os.Exit(ExitSetupFailed)
}
interfaceName := os.Args[1]
fmt.Fprintln(os.Stderr, "Warning: this is a test program for Windows, mainly used for debugging this Go package. For a real WireGuard for Windows client, the repo you want is <https://git.zx2c4.com/wireguard-windows/>, which includes this code as a module.")
logger := device.NewLogger(
device.LogLevelDebug,
fmt.Sprintf("(%s) ", interfaceName),
)
logger.Info.Println("Starting wireguard-go version", device.WireGuardGoVersion)
logger.Debug.Println("Debug log enabled")
tunDevice, err := tun.CreateTUN(interfaceName, 0)
//defer tunDevice.Close() _note_ the device.close() seems to be closing the tun so this is not needed
if err == nil {
realInterfaceName, err2 := tunDevice.Name()
if err2 == nil {
interfaceName = realInterfaceName
}
} else {
logger.Error.Println("Failed to create TUN device:", err)
os.Exit(ExitSetupFailed)
}
nativeTunDevice := tunDevice.(*tun.NativeTun)
wintunVersion, ndisVersion, err := nativeTunDevice.Version()
if err != nil {
log.Printf("Warning: unable to determine Wintun version: %v", err)
} else {
log.Printf("Using Wintun/%s (NDIS %s)", wintunVersion, ndisVersion)
}
log.Println("Dropping privileges")
err = elevate.DropAllPrivileges(true)
if err != nil {
serviceError = services.ErrorDropPrivileges
return
}
log.Println("Creating interface instance")
logOutput := log.New(ringlogger.Global, logPrefix, 0)
logger := &device.Logger{logOutput, logOutput, logOutput}
dev := device.NewDevice(wintun, logger)
luid := winipcfg.LUID(nativeTunDevice.LUID())
//xxx ip, ipnet, _ := net.ParseCIDR("10.82.31.4/24")
ip, ipnet, _ := net.ParseCIDR("169.254.100.200/32")
err = luid.SetIPAddresses([]net.IPNet{{ip, ipnet.Mask}})
if err != nil {
fatal(err)
}
err = luid.SetRoutes([]*winipcfg.RouteData{{*ipnet, ipnet.IP, 0}})
if err != nil {
fatal(err)
}
device := device.NewDevice(tunDevice, logger)
defer device.Close()
device.Up()
logger.Info.Println("Device started")
uapi, err := ipc.UAPIListen(interfaceName)
if err != nil {
logger.Error.Println("Failed to listen on uapi socket:", err)
os.Exit(ExitSetupFailed)
}
defer uapi.Close()
errs := make(chan error)
term := make(chan os.Signal, 1)
go func() {
for {
conn, err := uapi.Accept()
if err != nil {
errs <- err
return
}
go device.IpcHandle(conn)
}
}()
logger.Info.Println("UAPI listener started")
// wait for program to terminate
signal.Notify(term, os.Interrupt)
signal.Notify(term, os.Kill)
signal.Notify(term, syscall.SIGTERM)
select {
case <-term:
case <-errs:
case <-device.Wait():
}
*/
// clean up
// logger.Info.Println("Shutting down")
}
func fatal(v ...interface{}) {
panic(windows.StringToUTF16Ptr(fmt.Sprint(v...)))
func main() {
var r <-chan svc.ChangeRequest
var changes chan<- svc.Status
confPath := "c:\\git\\github\\ziti-windows-uwp\\wintun-testing\\simple.conf"
if envPath := os.Getenv("WIREGUARD_TESTING_CONF"); envPath != "" {
confPath = envPath
}
interfaceName := "ZitiTUN"
serviceError := services.ErrorSuccess
conf, err := conf.LoadFromPath(confPath)
if err != nil {
panic(err)
}
conf.DeduplicateNetworkEntries()
logPrefix := fmt.Sprintf("[%s] ", conf.Name)
log.SetPrefix(logPrefix)
log.Println("Starting", version.UserAgent())
if m, err := mgr.Connect(); err == nil {
if lockStatus, err := m.LockStatus(); err == nil && lockStatus.IsLocked {
/* If we don't do this, then the Wintun installation will block forever, because
* installing a Wintun device starts a service too. Apparently at boot time, Windows
* 8.1 locks the SCM for each service start, creating a deadlock if we don't announce
* that we're running before starting additional services.
*/
log.Printf("SCM locked for %v by %s, marking service as started", lockStatus.Age, lockStatus.Owner)
changes <- svc.Status{State: svc.Running}
}
m.Disconnect()
}
if serviceError != services.ErrorSuccess {
panic(serviceError)
}
var watcher *wireguard.InterfaceWatcher
log.Println("Watching network interfaces")
watcher, err = wireguard.WatchInterface()
if err != nil {
serviceError = services.ErrorSetNetConfig
return
}
log.Println("Resolving DNS names")
uapiConf, err := conf.ToUAPI()
if err != nil {
serviceError = services.ErrorDNSLookup
return
}
log.Println("Creating Wintun interface")
tunDevice, err := tun.CreateTUN(interfaceName, 0)
if err != nil {
serviceError = services.ErrorCreateWintun
return
}
defer tunDevice.Close()
nativeTun := tunDevice.(*tun.NativeTun)
wintunVersion, ndisVersion, err := nativeTun.Version()
if err != nil {
log.Printf("Warning: unable to determine Wintun version: %v", err)
} else {
log.Printf("Using Wintun/%s (NDIS %s)", wintunVersion, ndisVersion)
}
log.Println("Enabling firewall rules")
err = wireguard.EnableFirewall(conf, nativeTun)
if err != nil {
log.Printf("ERROR: %v", err)
serviceError = services.ErrorFirewall
return
}
log.Println("Enabling firewall rules")
err = wireguard.EnableFirewall(conf, nativeTun)
if err != nil {
serviceError = services.ErrorFirewall
return
}
log.Println("Dropping privileges")
err = elevate.DropAllPrivileges(true)
if err != nil {
serviceError = services.ErrorDropPrivileges
return
}
log.Println("Creating interface instance")
logOutput := log.New(ringlogger.Global, logPrefix, 0)
logger := &device.Logger{logOutput, logOutput, logOutput}
dev := device.NewDevice(tunDevice, logger)
log.Println("Setting interface configuration")
uapi, err := ipc.UAPIListen(conf.Name)
if err != nil {
serviceError = services.ErrorUAPIListen
return
}
ipcErr := dev.IpcSetOperation(bufio.NewReader(strings.NewReader(uapiConf)))
if ipcErr != nil {
err = ipcErr
serviceError = services.ErrorDeviceSetConfig
return
}
log.Println("Bringing peers up")
dev.Up()
watcher.Configure(dev, conf, nativeTun)
log.Println("Listening for UAPI requests")
go func() {
for {
conn, err := uapi.Accept()
if err != nil {
continue
}
go dev.IpcHandle(conn)
}
}()
changes <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop | svc.AcceptShutdown}
log.Println("Startup complete")
for {
select {
case c := <-r:
switch c.Cmd {
case svc.Stop, svc.Shutdown:
return
case svc.Interrogate:
changes <- c.CurrentStatus
default:
log.Printf("Unexpected service control request #%d\n", c)
}
case <-dev.Wait():
return
case e := <-watcher.Errors:
serviceError, err = e.ServiceError, e.Err
return
}
}
}
+15 -13
View File
@@ -1,16 +1,16 @@
package main
import (
"fmt"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/tun"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
"net"
"os"
"os/signal"
user2 "os/user"
"path/filepath"
"syscall"
"fmt"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/tun"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
"net"
"os"
"os/signal"
user2 "os/user"
"path/filepath"
"syscall"
)
const bufferSize = 64 * 1024
@@ -38,7 +38,6 @@ func main() {
fmt.Printf("error creating TUN device: (%v)\n", err)
os.Exit(1)
}
defer func() { _ = tunDevice.Close() }()
if name, err := tunDevice.Name(); err == nil {
fmt.Printf("created TUN device [%s]\n", name)
}
@@ -68,14 +67,17 @@ func main() {
fmt.Println("running")
for {
buffer := make([]byte, bufferSize)
n, err := tunDevice.Read(buffer, 0)
if err != nil {
fatal(err)
}
fmt.Printf("read [%d] bytes from TUN [%v]\n", n, buffer[:n])
fmt.Printf("read [%d] bytes [", n)
for i := 0; i < n; i++ {
fmt.Printf("%x ", buffer[i])
}
fmt.Println("]")
}
signal.Notify(term, os.Interrupt)