-
-
Save drio/858480d091ad1a4d72930732c9095768 to your computer and use it in GitHub Desktop.
The most fascinating thing...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The most fascinating thing I've learned recently is how userspace networking | |
works, particularly in mesh networks like Tailscale. | |
When you want to encrypt network traffic, you typically use a TUN/TAP device | |
provided by the operating system. At a high level, here's how (I think) it works: | |
When applications send data over the network via sockets, the data follows | |
the OS networking stack, which adds the necessary headers. If the destination | |
IP address matches your TUN device, the kernel redirects that packet to the | |
userland application controlling the TUN device (e.g., tailscaled). | |
This userland application then processes the packet however needed - in | |
Tailscale's case, typically encrypting and sending it over an established | |
WireGuard connection. For incoming traffic, packets reaching the network | |
interface are processed by the device driver and move up the network stack. | |
The kernel delivers these packets to tailscaled, which decrypts them and | |
reinjects them into the network stack for delivery to the appropriate | |
application. | |
But creating a TUN device requires root privileges. This is | |
where userspace networking becomes valuable. Tailscale's binary includes | |
a complete userspace TCP/IP stack from gVisor. When userspace networking is | |
enabled, you're still conceptually creating a TUN device, but at the userspace | |
level - socket creation uses gVisor's entry points instead of the kernel's. | |
The payload gets processed entirely in userspace. When Tailscale receives the | |
resulting IP or UDP packet, it encapsulates and sends it over another socket | |
through the WireGuard connection. This packet then flows through the kernel's | |
TCP stack before being transmitted. | |
This approach lets you join a device to a Tailscale network (a "tailnet") | |
without root access. With one limitation: other processes on that machine | |
cannot send data to the tailnet. To overcome this, you can use Tailscale's | |
SOCKS5 proxy feature with the --socks5-server flag. | |
This capability is truly mind-blowing. It's how Tailscale can run in browsers, | |
which lack traditional socket APIs and rely on technologies like WebSockets for | |
networking. One Tailscale engineer (Brad) has created a demonstration of this | |
concept. His implementation (from my understanding) tunnels WireGuard UDP | |
packets over WebSockets, using Tailscale's relay servers (DERP) which | |
"talk" websockets. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment