Who Logs You in When You Use Tailscale SSH?

stonecharioteer1 pts0 comments

Who Logs You In When You Use Tailscale SSH? | Stonecharioteer on Tech<br>I'm currently open to new opportunities! View my resume or connect on LinkedIn.<br>Table of ContentsTLDR<br>Normal SSH first<br>What Tailscale changes<br>The packet path<br>Who answers port 22?<br>How can Tailscale become a Unix user?<br>The OpenSSH way to get multiple policies<br>What happened to authorized_keys?<br>accept vs check<br>Trust boundariesThe local network<br>DERP<br>Tailscale control plane<br>Tailnet admins<br>The destination machine

How I debug the model<br>Ansible, GitHub Actions, and why I still used OpenSSH<br>Why this feels nicer than needing an exit node for SSH<br>The model I am keeping<br>References

I was setting up a machine recently and noticed something odd.<br>OpenSSH password authentication was disabled. The user I was logging in as did<br>not have anything useful in ~/.ssh/authorized_keys. I do not expose SSH on<br>this box to the internet either.<br>Regular SSH should have failed. This still worked:<br>tailscale ssh vinay@my-server

I got a shell as the local Unix user vinay.<br>That was the bit I wanted to understand. OpenSSH did not accept a password, and<br>it did not find a public key in authorized_keys. In this path, OpenSSH was not<br>the thing deciding whether I could log in. Tailscale was.<br>I have been using Tailscale more deliberately lately. I previously wrote about<br>setting up a Tailscale exit node, where the question was<br>mostly: how does traffic leave my machine and reach the internet through a home<br>gateway?<br>This post is me working through Tailscale SSH. I started with the assumption<br>that it was mostly a convenience wrapper around SSH. It is not quite that.<br>The questions I had were:<br>Is this still SSH?<br>Is sshd involved?<br>Where did my SSH keys go?<br>What exactly does Tailscale authenticate?<br>What does the Tailscale control plane know?<br>What can DERP see?<br>What role do local Linux users still play?<br>What permission does tailscaled have that lets it start a shell as that<br>Unix user?<br>TLDR#<br>Tailscale SSH still gives you an SSH session, but it is not an OpenSSH-server<br>login. The authentication decision moves from per-host SSH keys to Tailscale<br>identity and tailnet policy.<br>The path is:<br>Your devices are already connected through Tailscale&rsquo;s WireGuard mesh.<br>The destination machine has Tailscale SSH enabled with tailscale up --ssh.<br>The tailnet policy contains ssh rules saying which Tailscale users, groups,<br>or tagged devices can log in to which machines as which local Unix users.<br>When you connect to port 22 over the Tailscale address, tailscaled handles<br>the SSH connection on the tailnet interface.<br>Tailscale checks the source device/user identity against the central policy.<br>If allowed, the privileged tailscaled service starts a session as the<br>requested local Unix user.<br>The comparison I keep in my head is:<br>OpenSSH usually asks: &ldquo;Does this client have a key accepted by this host?&rdquo;<br>Tailscale SSH asks: &ldquo;Does this tailnet identity, from this device, have policy<br>permission to become this local user on this node?&rdquo;

The local Unix account still matters. Tailscale does not bypass Linux<br>permissions. If I log in as vinay, I get vinay&rsquo;s files, groups, shell, and<br>sudo rules. Tailscale can create the session because tailscaled runs as a<br>privileged system service on the destination machine.<br>Normal SSH first#<br>Before Tailscale enters the picture, this is the usual OpenSSH flow:<br>{"label": "laptop", "sub": "SSH client", "detail": "Opens a TCP connection to port 22 and speaks the SSH protocol."},<br>{"label": "server : sshd", "via": "TCP / 22", "sub": "listens on :22", "detail": "OpenSSH answers, proves its host key, then checks your key or password against authorized_keys / PAM before starting a session."}<br>Classic OpenSSH: the client talks straight to sshd on TCP 22.A simplified version of the flow:<br>The client connects to the server on TCP port 22.<br>Client and server negotiate encryption for the SSH transport.<br>The server proves its identity using a host key.<br>The client authenticates as a local username, usually with a private key.<br>sshd checks files like ~/.ssh/authorized_keys for that local user.<br>If accepted, sshd creates a login session as that Unix user.<br>The protocol is not the problem. The annoying part is access distribution:<br>every server needs the right public keys;<br>removing someone&rsquo;s access means removing keys everywhere;<br>host keys need to be trusted or managed;<br>if you have many machines, access review becomes annoying.<br>This is not an argument against OpenSSH. I use it everywhere. The point is that<br>key distribution and access policy become your distributed system.<br>OpenSSH certificates solve a related key-distribution problem, but they still<br>use sshd as the login broker. Tailscale SSH moves the authorization decision<br>into tailnet policy.<br>What Tailscale changes#<br>Tailscale already gives every device in your tailnet a cryptographic identity and<br>a stable private address. My laptop and my server do not need a public inbound<br>port open to find each other. They can establish a...

tailscale openssh user local server unix

Related Articles