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

tailscale-wsl2

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
Owner
Danny Hermes
Software Engineer and PhD Mathematician
Danny Hermes
Similar Resources

A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet.

A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet.

frp README | 中文文档 What is frp? frp is a fast reverse proxy to help you expose a local server behind a NAT or firewall to the Internet. As of now, it s

Jan 5, 2023

4chain is a simple、fast reverse proxy to help you expose a local server behind a NAT or firewall to the Internet.

4Chain What is 4chain? 4chain is a simple、fast reverse proxy to help you expose a local server behind a NAT or firewall to the Internet. Using the ssh

Nov 1, 2022

A TCP proxy used to expose services onto a tailscale network without root. Ideal for container environments.

tailscale-sidecar This is barely tested software, I don't guarantee it works but please make an issue if you use it and find a bug. Pull requests are

Dec 30, 2022

Headscale - An open source, self-hosted implementation of the Tailscale control server

Headscale - An open source, self-hosted implementation of the Tailscale control server

Dec 29, 2022

A memory-safe SSH server, focused on listening only on VPN networks such as Tailscale

Features Is tested to work with SCP Integrates well with systemd Quickstart Download binary for your architecture. We only support Linux. If you don't

Jun 10, 2022

Cdn - CDN microservice to upload files to zachlatta.com that only accepts traffic from Tailscale IPs

cdn CDN microservice to upload files to zachlatta.com that only accepts traffic from Tailscale IPs. source code available at https://github.com/zachla

Jun 26, 2022

Tscert - Minimal package for just the HTTPS cert fetching part of the Tailscale client API

tscert This is a stripped down version of the tailscale.com/client/tailscale Go

Nov 27, 2022

Provides agent and server plugins for SPIRE to allow Tailscale node attestation.

SPIRE Tailscale Plugin ⚠️ this node attestation plugin relies on a Tailscale OIDC id-token feature, which is marked as Work-in-Progress and may not be

May 22, 2022

An unofficial GUI wrapper around the Tailscale CLI client.

An unofficial GUI wrapper around the Tailscale CLI client.

Trayscale Trayscale is an unofficial GUI wrapper around the Tailscale CLI client, particularly for use on Linux, as no official Linux GUI client exist

Dec 26, 2022
Tailscale-client-go - A client implementation for the Tailscale HTTP API

tailscale-client-go A client implementation for the Tailscale HTTP API Example p

Sep 8, 2022
Automatically update your Windows hosts file with the WSL2 VM IP address

Automatically update your Windows hosts file with the WSL2 VM IP address

Jan 9, 2023
Example of how to write reverse proxy in Go that runs on Cloud Run with Tailscale

Cloudrun Tailscale Reverse Proxy Setup Create a ephemeral key in Tailscale Set TAILSCALE_AUTHKEY in your Cloud Run environment variables Set TARGET_UR

Dec 18, 2022
Automatically spawn a reverse shell fully interactive for Linux or Windows victim
Automatically spawn a reverse shell fully interactive for Linux or Windows victim

Girsh (Golang Interactive Reverse SHell) Who didn't get bored of manually typing the few lines to upgrade a reverse shell to a full interactive revers

Dec 14, 2022
gproxy is a tiny service/library for creating lets-encrypt/acme secured gRPC and http reverse proxies
gproxy is a tiny service/library for creating lets-encrypt/acme secured gRPC and http reverse proxies

gproxy is a reverse proxy service AND library for creating flexible, expression-based, lets-encrypt/acme secured gRPC/http reverse proxies GProxy as a

Sep 11, 2022
A wrapper for cloudflared that manages your local proxies for you

Cloudflared Tunnel Wrapper cfdtunnel is a wrapper for cloudflared access tunnel, designed to access multiple tunnels without having to worry about you

Dec 16, 2022
Simple utility to set the WSL2 subnet to a specific range

WSL subnet utility This is a small Go utility to set the WSL2 host and subnet. It achieves this by: deleting the existing WSL network creating a new o

Oct 22, 2022
Mar 21, 2022
An SSH key pair generator
An SSH key pair generator

Keygen An SSH key pair generator. Supports generating RSA and Ed25519 keys. Example k, err := NewWithWrite(".ssh", "my_awesome_key", []byte(""), key.E

Dec 24, 2022
Simple reverse shell to avoid Windows defender and kaspersky detection
Simple reverse shell to avoid Windows defender and kaspersky detection

Windows-ReverseShell Simple reverse shell to avoid Windows defender, kaspersky d

Oct 19, 2022