Skip to content

A pair of local reverse proxies (one in Windows, one in Linux) for Tailscale on WSL2

License

Notifications You must be signed in to change notification settings

dhermes/tailscale-wsl2

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tailscale-wsl2

See: tailscale/tailscale#3530

TL;DR

Running two reverse proxies (one in Windows, one in the WSL2 Linux VM), the Windows Tailscale daemon can be accessed via WSL2:

$ tailscale ip
100.101.102.102
$
$ tailscale status
100.101.102.102 suspicious-hawking   dhermes@     windows -
100.101.102.103 pedantic-yonath      dhermes@     linux   -

Why?

On standard Linux, tailscaled runs via systemd and makes deep modifications to network interfaces and routing to make sure Tailscale packets get handled by Tailscale. However, on WSL2 there is no systemd and the Linux VM doesn't have "real" control of Windows host networking, so running tailscale directly in WSL2 isn't really an option.

However, Tailscale for Windows is a perfectly good choice and all of the host networking changes made by it are still visible to the WSL2 VM. This means things like Tailscale DNS and Tailscale routing "just work"

$ nslookup pedantic-yonath
Server:         100.100.100.100
Address:        100.100.100.100#53

Name:   pedantic-yonath.dhermes.github.beta.tailscale.net
Address: 100.101.102.103

$
$ ssh dhermes@pedantic-yonath
dhermes@pedantic-yonath:~$
dhermes@pedantic-yonath:~$ tailscale ip -4
100.101.102.103

However, from the Linux side of WSL2, there is still no direct way to get information about the current device and other parts of the Tailnet:

$ tailscale ip -4
Failed to connect to local Tailscale daemon for /localapi/v0/status; not running?
Error: dial unix /var/run/tailscale/tailscaled.sock: connect: no such file or directory

This repository provides two reverse proxy binaries (one for Windows, one for Linux) that make it possible to directly reference the Windows-managed Tailscale daemon from inside the WSL2 VM.

How?

On Linux, the tailscale binary expects to communicate with tailscaled via a Unix Domain Socket (UDS) at /var/run/tailscale/tailscaled.sock. However, Windows (i.e. not Unix-y) doesn't have a UDS equivalent, so there isn't even a host socket that the WSL2 VM could try to interact with. Due to this Windows feature difference, the Tailscale daemon runs as a cleartext HTTP service on localhost:41112 (as of Tailscale 1.18.1).

Unfortunately the local network interface on Windows is (intentionally) not exposed to the WSL2 VM. However, there is a virtual network interface that can be used to bridge the Windows host to the WSL2 VM:

PS C:\Users\dhermes> ipconfig

Windows IP Configuration

...
Ethernet adapter vEthernet (WSL):

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::ed6d:71c5:2607:3ce6%22
   IPv4 Address. . . . . . . . . . . : 172.27.64.1
   Subnet Mask . . . . . . . . . . . : 255.255.240.0
   Default Gateway . . . . . . . . . :
...

To expose the Tailscale daemon to the WSL2 VM, we bind a server to the virtual network IP (e.g. here 172.27.64.1) and run a reverse proxy in Windows that will be available to the WSL2 VM:

PS C:\Users\dhermes\tailscale-wsl2> go install .\cmd\tailscale-wsl2-windows\
PS C:\Users\dhermes\tailscale-wsl2> tailscale-wsl2-windows.exe --vethernet-wsl-ip 172.27.64.1

Running a TCP reverse proxy is super easy with the super awesome inet.af/tcpproxy package. This package was of course created by the lovely folks at Tailscale. They also made the inet.af/wf package for Windows Firewall operations, which turns out to be necessary to bind to the virtual network IP. See Windows Firewall for more information about which firewall rules are necessary.

But, this only solves half of the problem. The tailscale CLI still assumes it will have a UDS to talk to. To solve this problem, we run a second reverse proxy, but on the Linux side of the house:

$ go install ./cmd/tailscale-wsl2-linux/
$ sudo tailscale-wsl2-linux --host-ip 172.27.64.1 --tailscale-socket /var/run/tailscale/tailscaled.sock

The default value of --tailscale-socket is actually /var/run/tailscale/wsl2-tailscaled.sock to avoid colliding with the socket that tailscaled expects to be the owner of. If that default is used instead then it needs to be explicitly provided to tailscale

$ tailscale --socket /var/run/tailscale/wsl2-tailscaled.sock ip -4
100.101.102.102

Having the client and server version mismatch is not great and actually causes the server to reject some requests:

$ tailscale ip -4
Warning: client version "1.18.1-t0a4334048-gb05dc05d4" != tailscaled server version "1.18.0-t22d969975-g7022e5a4c"
100.101.102.102
$ tailscale ping pedantic-yonath
Warning: client version "1.18.1-t0a4334048-gb05dc05d4" != tailscaled server version "1.18.0-t22d969975-g7022e5a4c"
2021/12/05 19:47:58 GotNotify: Version mismatch! frontend="1.18.1-t0a4334048-gb05dc05d4" backend="1.18.0-t22d969975-g7022e5a4c"
Notify.ErrMessage: GotNotify: Version mismatch! frontend="1.18.1-t0a4334048-gb05dc05d4" backend="1.18.0-t22d969975-g7022e5a4c"

Installing tailscale from source is probably the best plan to ensure this version mismatch doesn't occur, but at least for now the custom APT package matches the Windows version:

$ tailscale version
1.18.1
  tailscale commit: 0a43340482a86c3c227aa133c8f1ee9e36360b4b
  other commit: b05dc05d46c4a3c7e634ef0695221985be99274d
  go version: go1.17.2-ts7037d3ea51
$ [sudo] apt-get install tailscale=1.18.0
$ tailscale version
1.18.0
  tailscale commit: 22d9699759fa34247153a542e9c4af5696c01fdf
  other commit: 7022e5a4ccce1d12fbe4f679d641d816d81491a1
  go version: go1.17.2-ts7037d3ea51
$
$ tailscale ip -4
100.101.102.102
$ tailscale ping pedantic-yonath
pong from pedantic-yonath (100.101.102.103) via 192.168.7.131:41641 in 5ms

About

A pair of local reverse proxies (one in Windows, one in Linux) for Tailscale on WSL2

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages