Skip to content

Commit

Permalink
use gvisor-tap-vsock (#91)
Browse files Browse the repository at this point in the history
* use gvisor

* pull binaries on build

* make values configurable

* just extract binaries from tar.gz

* add entry for host.internal

* leave resolv.conf alone

* restore ip addr for eth0...?

* wait for dhcp to add default route
  • Loading branch information
sakai135 authored Feb 7, 2022
1 parent 0d58c6b commit 63d90e0
Show file tree
Hide file tree
Showing 14 changed files with 1,662 additions and 156 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
CONTAINER_ID=$(docker create $TAG_NAME)
docker export $CONTAINER_ID | gzip > wsl-vpnkit.tar.gz
sha256sum wsl-vpnkit.tar.gz | tee wsl-vpnkit.tar.gz.sha256
ls -la wsl-vpnkit.tar.gz wsl-vpnkit.tar.gz.sha256
ls -la wsl-vpnkit.tar.gz
- name: Artifacts
uses: actions/upload-artifact@v2
with:
Expand Down
44 changes: 18 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# wsl-vpnkit

The `wsl-vpnkit` script uses [VPNKit](https://github.com/moby/vpnkit) and [npiperelay](https://github.com/jstarks/npiperelay) to provide network connectivity to the WSL 2 VM while connected to VPNs on the Windows host. This requires no settings changes or admin privileges on the Windows host.
The `wsl-vpnkit` script uses [gvisor-tap-vsock](https://github.com/containers/gvisor-tap-vsock) to provide network connectivity to the WSL 2 VM while connected to VPNs on the Windows host. This requires no settings changes or admin privileges on the Windows host.

The releases bundle the script together with VPNKit and npiperelay in an [Alpine](https://alpinelinux.org/) distro.
The releases bundle the script together with the binaries in an [Alpine](https://alpinelinux.org/) distro.

## Setup

Expand All @@ -24,7 +24,7 @@ wsl.exe -d wsl-vpnkit service wsl-vpnkit start
### Notes

* Ports on the WSL 2 VM are accessible from the Windows host using `localhost`.
* Ports on the Windows host are accessible from WSL 2 using `host.internal`, `192.168.67.2`, or [the IP address of the host machine](https://docs.microsoft.com/en-us/windows/wsl/networking#accessing-windows-networking-apps-from-linux-host-ip).
* Ports on the Windows host are accessible from WSL 2 using `host.internal`, `192.168.67.2` or [the IP address of the host machine](https://docs.microsoft.com/en-us/windows/wsl/networking#accessing-windows-networking-apps-from-linux-host-ip).

### Update

Expand All @@ -34,7 +34,7 @@ To update, unregister the existing distro and import the new version.
# PowerShell
wsl --unregister wsl-vpnkit
wsl --import wsl-vpnkit $env:USERPROFILE\wsl-vpnkit wsl-vpnkit.tar.gz
wsl --import wsl-vpnkit $env:USERPROFILE\wsl-vpnkit wsl-vpnkit.tar.gz --version 2
```

### Uninstall
Expand Down Expand Up @@ -64,32 +64,24 @@ cd wsl-vpnkit/
The `wsl-vpnkit` script can be used as a normal script in your existing distro. This is an example setup script for Ubuntu.

```sh
# create the directory to place Windows executables
# download wsl-vpnkit
VERSION=v0.3.x
wget https://github.com/sakai135/wsl-vpnkit/releases/download/$VERSION/wsl-vpnkit.tar.gz
tar --strip-components=1 -xf wsl-vpnkit.tar.gz app/wsl-vpnkit files/wsl-gvproxy.exe files/wsl-vm
rm wsl-vpnkit.tar.gz

# place Windows exe
USERPROFILE=$(wslpath "$(powershell.exe -c 'Write-Host -NoNewline $env:USERPROFILE')")
mkdir -p "$USERPROFILE/wsl-vpnkit"
mv wsl-gvproxy.exe "$USERPROFILE/wsl-vpnkit/wsl-gvproxy.exe"

# install socat and 7z; p7zip-full can be removed after install
sudo apt install p7zip-full socat

# download VPNKit binaries
wget https://github.com/sakai135/vpnkit/releases/download/v0.5.0-20211026/vpnkit-tap-vsockd
wget https://github.com/sakai135/vpnkit/releases/download/v0.5.0-20211026/vpnkit.exe
mv vpnkit.exe "$USERPROFILE/wsl-vpnkit/wsl-vpnkit.exe"
chmod +x vpnkit-tap-vsockd
sudo chown root:root vpnkit-tap-vsockd
sudo mv vpnkit-tap-vsockd /usr/local/sbin/vpnkit-tap-vsockd

# download npiperelay
wget https://github.com/jstarks/npiperelay/releases/download/v0.1.0/npiperelay_windows_amd64.zip
7z e npiperelay_windows_amd64.zip npiperelay.exe
rm npiperelay_windows_amd64.zip
mv npiperelay.exe "$USERPROFILE/wsl-vpnkit/"

# download the wsl-vpnkit script to current directory
wget https://raw.githubusercontent.com/sakai135/wsl-vpnkit/main/wsl-vpnkit
chmod +x wsl-vpnkit
# place Linux bin
chmod +x wsl-vm
sudo chown root:root wsl-vm
sudo mv wsl-vm /usr/local/sbin/wsl-vm

# run the wsl-vpnkit script
chmod +x wsl-vpnkit
sudo ./wsl-vpnkit
```

Expand All @@ -111,5 +103,5 @@ For this and other networking considerations when using WSL 2, see [Accessing ne
# PowerShell
wsl --shutdown
kill -Name wsl-vpnkit
kill -Name wsl-gvproxy
```
133 changes: 133 additions & 0 deletions cmd/gvproxy/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package main

import (
"context"
"flag"
"net"
"os"
"os/signal"
"syscall"

"github.com/containers/gvisor-tap-vsock/pkg/types"
"github.com/containers/gvisor-tap-vsock/pkg/virtualnetwork"
"github.com/pkg/errors"
"github.com/sakai135/wsl-vpnkit/pkg/transport"
log "github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
)

var (
debug bool
mtu int

exitCode int

subnet string
gatewayIP string
hostIP string
vmIP string
)

const (
gatewayMacAddress = "5a:94:ef:e4:0c:dd"
vmMacAddress = "5a:94:ef:e4:0c:ee"
)

func main() {
log.SetOutput(os.Stderr)

flag.BoolVar(&debug, "debug", false, "Print debug info")
flag.IntVar(&mtu, "mtu", 1500, "Set the MTU")

flag.StringVar(&subnet, "subnet", "192.168.127.0/24", "Set the subnet")
flag.StringVar(&gatewayIP, "gateway-ip", "192.168.127.1", "Set the IP for the gateway")
flag.StringVar(&hostIP, "host-ip", "192.168.127.254", "Set the IP for accessing the host from the WSL 2 VM")
flag.StringVar(&vmIP, "vm-ip", "192.168.127.2", "Set the IP for the WSL 2 VM")

flag.Parse()
ctx, cancel := context.WithCancel(context.Background())
// Make this the last defer statement in the stack
defer os.Exit(exitCode)

groupErrs, ctx := errgroup.WithContext(ctx)
// Setup signal channel for catching user signals
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)

if debug {
log.SetLevel(log.DebugLevel)
}

config := types.Configuration{
Debug: debug,
CaptureFile: "",
MTU: mtu,
Subnet: subnet,
GatewayIP: gatewayIP,
GatewayMacAddress: gatewayMacAddress,
DHCPStaticLeases: map[string]string{
vmIP: vmMacAddress,
},
DNS: []types.Zone{
{
Name: "internal.",
Records: []types.Record{
{
Name: "gateway",
IP: net.ParseIP(gatewayIP),
},
{
Name: "host",
IP: net.ParseIP(hostIP),
},
},
},
},
DNSSearchDomains: nil,
Forwards: map[string]string{},
NAT: map[string]string{
hostIP: "127.0.0.1",
},
GatewayVirtualIPs: []string{hostIP},
VpnKitUUIDMacAddresses: map[string]string{
"c3d68012-0208-11ea-9fd7-f2189899ab08": vmMacAddress,
},
Protocol: types.HyperKitProtocol,
}

groupErrs.Go(func() error {
return run(ctx, groupErrs, &config)
})

// Wait for something to happen
groupErrs.Go(func() error {
select {
// Catch signals so exits are graceful and defers can run
case <-sigChan:
cancel()
return errors.New("signal caught")
case <-ctx.Done():
return nil
}
})
// Wait for all of the go funcs to finish up
if err := groupErrs.Wait(); err != nil {
log.Error(err)
exitCode = 1
}
}

func run(ctx context.Context, g *errgroup.Group, configuration *types.Configuration) error {
vn, err := virtualnetwork.New(configuration)
if err != nil {
return err
}

conn := transport.GetStdioConn()
err = vn.AcceptQemu(ctx, conn)
if err != nil {
return err
}

return nil
}
Loading

0 comments on commit 63d90e0

Please sign in to comment.