/wsl-vpnkit

Use VPNKit to get around issues running WSL2 with a VPN

Primary LanguageShell

wsl-vpnkit

Uses VPNKit to provide network connectivity to the WSL2 VM. This requires no settings changes or admin privileges on the Windows host.

For a detailed look at how this works, see this explanation of how VPNKit works. vpnkit-tap-vsockd acts as the network device inside the WSL VM, and vpnkit handles the requests on the Windows host. This uses socat and npiperelay to take advantage of the WSL inter-process integration instead of setting up a new Hyper-V socket integration service.

Setup

Install vpnkit.exe and vpnkit-tap-vsockd

This step expects Docker Desktop for Windows to be installed. Alternatively, build vpnkit.exe and vpnkit-tap-vsockd from VPNKit.

With Docker Desktop installed, vpnkit.exe is ready for use. Extract vpnkit-tap-vsockd from Docker Desktop:

sudo apt install genisoimage
isoinfo -i /mnt/c/Program\ Files/Docker/Docker/resources/wsl/docker-for-wsl.iso -R -x /containers/services/vpnkit-tap-vsockd/lower/sbin/vpnkit-tap-vsockd > ./vpnkit-tap-vsockd
chmod +x vpnkit-tap-vsockd
sudo mv vpnkit-tap-vsockd /sbin/vpnkit-tap-vsockd
sudo chown root:root /sbin/vpnkit-tap-vsockd

Install npiperelay.exe

Download from npiperelay.

sudo apt install unzip
wget https://github.com/jstarks/npiperelay/releases/download/v0.1.0/npiperelay_windows_amd64.zip
unzip npiperelay_windows_amd64.zip npiperelay.exe
rm npiperelay_windows_amd64.zip
mkdir /mnt/c/bin
mv npiperelay.exe /mnt/c/bin/
sudo ln -s /mnt/c/bin/npiperelay.exe /usr/local/bin/npiperelay.exe

Install socat

sudo apt install socat

Configure DNS for WSL

Disable WSL from generating and overwriting /etc/resolv.conf.

sudo tee /etc/wsl.conf <<EOL
[network]
generateResolvConf = false
EOL

Manually set DNS servers to use when not running this script. 1.1.1.1 is provided as an example.

sudo tee /etc/resolv.conf <<EOL
nameserver 1.1.1.1
EOL

Configure http_proxy.json and gateway_forwards.json

This step is only necessary for using a HTTP proxy or exposing some service from the Windows host to the WSL2 VM through VPNKit.

Set the variables VPNKIT_HTTP_CONFIG and/or VPNKIT_GATEWAY_FORWARD_CONFIG to the Windows host path to these configuration files. Example values are provided in ./wsl-vpnkit for using the configuration generated by Docker Desktop.

Docker Desktop will automatically generate and update http_proxy.json and gateway_forwards.json while Docker Desktop is running Docker. These configuration values generated by Docker Desktop will only work while Docker Desktop is running Docker.

http_proxy.json points to any HTTP proxies that might be configured on the Windows host. Use an empty object {} as its value for no proxy.

gateway_forwards.json points to any services to forward to the WSL2 VM. DNS can be configured here if the default Windows host's resolver is not desired. See an example from VPNKit.

Configure VS Code Remote WSL Extension

This is an optional workaround if the VPN on the Windows host blocks connections to the WSL2 VM and VS Code takes a while to open files within WSL2.

~\.vscode\extensions\ms-vscode-remote.remote-wsl-0.44.5\dist\wslDaemon.js

Look for something like this:

async function P(e,t,s){if(l.isWSL1(s))return"127.0.0.1";}

Insert ::1 to force use of IPv6 localhost:

async function P(e,t,s){return"::1";if(l.isWSL1(s))return"127.0.0.1";}

Run

sudo ./wsl-vpnkit

Keep this terminal open.

In some environments, explicitly pass the environment variable WSL_INTEROP to sudo.

sudo --preserve-env=WSL_INTEROP ./wsl-vpnkit

Services on the WSL2 VM should be accessible from the Windows host using localhost through the WSL networking integrations. Services on the Windows host should be accessible using the IP from VPNKIT_HOST_IP (192.168.67.2).

Troubleshooting

Ensure Docker Desktop is setup for WSL2 integration

If using Docker Desktop's http_proxy.json and gateway_forwards.json, ensure that Docker Desktop is setup for WSL2 integration and is running Docker. See this Docker blog post if running Windows 10 1903 or 1909.

Try shutting down WSL VM to reset

wsl.exe --shutdown

Check for a vpnkit.exe process listening on \\.\pipe\wsl-vpnkit and kill that too.

Check for the required processes

ps aux | grep wsl-vpnkit
  • socat ... npiperelay.exe
  • vpnkit.exe
  • vpnkit-tap-vsockd