From be276aef0b04afdd79803fc04c3010452b6ea803 Mon Sep 17 00:00:00 2001 From: Artem Lukyanov Date: Mon, 27 Dec 2021 14:21:51 +0300 Subject: [PATCH] Add Windows support --- .github/workflows/build.sh | 7 ++-- README.md | 3 ++ cli/up.go | 2 +- tun/tun.go | 5 ++- tun/tun_windows.go | 72 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 tun/tun_windows.go diff --git a/.github/workflows/build.sh b/.github/workflows/build.sh index 3ae337f..2354213 100644 --- a/.github/workflows/build.sh +++ b/.github/workflows/build.sh @@ -1,12 +1,13 @@ #!/bin/bash -platforms=("linux/amd64" "linux/arm" "linux/arm64" "darwin/amd64" "darwin/arm64") +platforms=("linux/amd64" "linux/arm" "linux/arm64" "darwin/amd64" "darwin/arm64" "windows/amd64" "windows/386") for platform in "${platforms[@]}" do platform_split=(${platform//\// }) GOOS=${platform_split[0]} GOARCH=${platform_split[1]} - env GOOS=$GOOS GOARCH=$GOARCH CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/hyprspace/hyprspace/cli.appVersion=$1" -o hyprspace-$1-${GOOS}-${GOARCH} . + [ $GOOS == "windows" ] && EXT=".exe" + env GOOS=$GOOS GOARCH=$GOARCH CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/hyprspace/hyprspace/cli.appVersion=$1" -o hyprspace-$1-${GOOS}-${GOARCH}${EXT} . -done \ No newline at end of file +done diff --git a/README.md b/README.md index 4967dc3..553c3a9 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ If you're running Hyprspace on a Mac you'll need to install `iproute2mac`. If yo ```bash brew install iproute2mac ``` +If you're running Hyprspace on Windows you'll need to install [tap-windows](http://build.openvpn.net/downloads/releases/). ### Installation @@ -88,6 +89,8 @@ but yours could be anything you'd like. (Note: if you're using a Mac you'll have to use the interface name `utun[0-9]`. Check which interfaces are already in use by running `ip a` once you've got `iproute2mac` installed.) +(Note: if you're using Windows you'll have to use the interface name as seen in Control Panel. IP address will be set automatically only if you run Hyprspace as Administrator.) + ###### Local Machine ```bash sudo hyprspace init hs0 diff --git a/cli/up.go b/cli/up.go index 4d2d9e1..2fa0a5e 100644 --- a/cli/up.go +++ b/cli/up.go @@ -98,7 +98,7 @@ func UpRun(r *cmd.Root, c *cmd.Sub) { fmt.Println("[+] Creating TUN Device") // Create new TUN device - iface, err = tun.New(cfg.Interface.Name) + iface, err = tun.New(cfg.Interface.Name, cfg.Interface.Address) if err != nil { checkErr(errors.New("interface already in use")) } diff --git a/tun/tun.go b/tun/tun.go index 912e8ea..d87b4f4 100644 --- a/tun/tun.go +++ b/tun/tun.go @@ -1,3 +1,6 @@ +//go:build !windows +// +build !windows + package tun import ( @@ -8,7 +11,7 @@ import ( ) // New creates and returns a new TUN interface for the application. -func New(name string) (result *water.Interface, err error) { +func New(name string, address string) (result *water.Interface, err error) { // Setup TUN Config cfg := water.Config{ DeviceType: water.TUN, diff --git a/tun/tun_windows.go b/tun/tun_windows.go new file mode 100644 index 0000000..99cc55a --- /dev/null +++ b/tun/tun_windows.go @@ -0,0 +1,72 @@ +//go:build windows +// +build windows + +package tun + +import ( + "os/exec" + "net" + "fmt" + + "github.com/songgao/water" +) + +// New creates and returns a new TUN interface for the application. +func New(name string, address string) (result *water.Interface, err error) { + // TUN on Windows requires address and network to be set on device creation stage + // We also set network to 0.0.0.0/0 so we able to reach networks behind the node + // https://github.com/songgao/water/blob/master/params_windows.go + // https://gitlab.com/openconnect/openconnect/-/blob/master/tun-win32.c + ip, _, err := net.ParseCIDR(address) + if err != nil { + return nil, err + } + network := net.IPNet{ + IP: ip, + Mask: net.IPv4Mask(0,0,0,0), + } + // Setup TUN Config + cfg := water.Config{ + DeviceType: water.TUN, + PlatformSpecificParams: water.PlatformSpecificParams{ + ComponentID: "tap0901", + InterfaceName: name, + Network: network.String(), + }, + } + // Create TUN Interface + result, err = water.New(cfg) + return +} + +// SetMTU sets the Maximum Tansmission Unit Size for a +// Packet on the interface. +func SetMTU(name string, mtu int) (err error) { + return netsh("interface", "ipv4", "set", "subinterface", name, "mtu=", fmt.Sprintf("%d", mtu)) +} + +// SetAddress sets the interface's known address and subnet. +func SetAddress(name string, address string) (err error) { + return netsh("interface", "ip", "set", "address", "name=", name, "static", address) +} + +// Up brings up an interface to allow it to start accepting connections. +func Up(name string) (err error) { + return +} + +// Down brings down an interface stopping active connections. +func Down(name string) (err error) { + return +} + +// Delete removes a TUN device from the host. +func Delete(name string) (err error) { + return +} + +func netsh(args ...string) (err error) { + cmd := exec.Command("netsh", args...) + err = cmd.Run() + return +}