# How to SSH to a Tailcat Server Using Its Token

> Effortlessly SSH to a Tailcat server using its token. The Tailcat CLI simplifies connections through WireGuard tunnels for secure, auth-free access. Learn how now.

- Repository: [Tailscale/tailcat](https://github.com/tailscale/tailcat)
- Tags: how-to-guide
- Published: 2026-08-30

---

**Run `tailcat ssh <token>` to connect to an auth-free SSH server, where the Tailcat CLI automatically constructs a proxy command that tunnels traffic through the WireGuard connection encoded in the token.**

Tailcat is an experimental WireGuard-based tunneling tool from the `tailscale/tailcat` repository that encodes server connection details into a self-contained token called a **ConnBlob**. When running the built-in auth-free SSH server, you can SSH into a Tailcat instance using only this token, eliminating the need for public IP addresses, port forwarding, or traditional SSH host key management.

## Understanding Tailcat Connection Tokens (ConnBlob)

A **ConnBlob** (connection blob) is a compact token that embeds a server's WireGuard public key and DERP relay information required to establish a peer-to-peer tunnel. When a server starts with the `--serve=no-auth-ssh` flag, it generates and displays a token beginning with `tc` followed by encoded connection parameters. This token contains everything the client needs to locate and authenticate with the server.

## Starting the Auth-Free SSH Server

To expose an SSH service through Tailcat, start the server with the dedicated serve flag. This mode does not require the client to possess SSH host keys or user credentials.

```bash
$ tailcat --serve=no-auth-ssh

# 🐈 Server listening with new address: tc1a2b3c4d5e6f7g8h9i0j

```

Copy the generated token (e.g., `tc1a2b3c4d5e6f7g8h9i0j`) for use on the client side.

## Connecting from the Client

The Tailcat CLI provides a dedicated `ssh` subcommand that wraps the system OpenSSH client. This command interprets the token, constructs the appropriate proxy configuration, and establishes the connection.

**Interactive shell:**

```bash
$ tailcat ssh tc1a2b3c4d5e6f7g8h9i0j

```

**Execute a remote command:**

```bash
$ tailcat ssh tc1a2b3c4d5e6f7g8h9i0j ls -la /home/$(whoami)

```

**Custom SSH port:**

```bash
$ tailcat ssh -p 2222 tc1a2b3c4d5e6f7g8h9i0j uptime

```

## How the SSH Integration Works Under the Hood

The seamless connection relies on the Tailcat CLI generating a proxy command and the server handling connections over the WireGuard tunnel.

### The Client-Side Proxy Command

In [`cmd/tailcat/ssh.go`](https://github.com/tailscale/tailcat/blob/main/cmd/tailcat/ssh.go), the `clientSSHMode` function orchestrates the connection. It locates the system `ssh` binary and builds a `ProxyCommand` that invokes the Tailcat binary itself to handle the WireGuard tunneling.

The proxy command takes the form:

```bash
tailcat --key="<key-name>" [--derpmap-url="<url>"] <token> <port>

```

Where `<port>` defaults to `22` unless overridden with the `-p` flag.

The `clientSSHMode` function then executes the system SSH client with strict options to bypass host key verification:

```bash
ssh -o UpdateHostKeys=no \
    -o StrictHostKeyChecking=no \
    -o UserKnownHostsFile=/dev/null \
    -o LogLevel=ERROR \
    -o ProxyCommand="tailcat --key=\"default\" tc1a2b3c4d5e6f7g8h9i0j 22" \
    tailcat-<hash>

```

### Deterministic Host Naming

Because OpenSSH uses the destination hostname in its `ControlPath` for connection multiplexing, Tailcat generates a deterministic label via the `sshDestHost` function. This function computes a SHA-256 hash of the token and returns a short string in the format `tailcat-<8-byte-hex>`, preventing socket conflicts while maintaining a consistent identifier for the session.

### Server-Side Connection Handling

When the tunneled TCP connection reaches the server, the `HandleTailscaleSSHConn` function in [`tailcat_ssh.go`](https://github.com/tailscale/tailcat/blob/main/tailcat_ssh.go) takes over. This implementation uses the `gliderlabs/ssh` library to wrap the connection, generates an **ed25519 host key** on first use, and spawns the user's login shell or executes the supplied command without requiring additional authentication.

## Summary

- **ConnBlob tokens** encode WireGuard keys and DERP relay information needed to reach the server.
- Start the auth-free server with `tailcat --serve=no-auth-ssh` to obtain a connection token.
- Use `tailcat ssh <token>` to connect; the CLI automatically configures the `ProxyCommand` to route through the WireGuard tunnel.
- The client generates a deterministic hostname (`tailcat-<hash>`) to manage OpenSSH control sockets correctly.
- Server-side handling in [`tailcat_ssh.go`](https://github.com/tailscale/tailcat/blob/main/tailcat_ssh.go) provides encryption via WireGuard and executes commands without traditional SSH authentication.

## Frequently Asked Questions

### Do I need to configure SSH host keys or authorized_keys on the server?

No. The Tailcat auth-free SSH server generates an ed25519 host key automatically on first use and does not verify client credentials. Authentication is implicitly handled by the WireGuard tunnel established via the connection token.

### What port does Tailcat SSH use by default?

The default port is **22**. You can specify a different port using the `-p` flag in the `tailcat ssh` command, which passes the port number to both the proxy command and the system SSH client.

### Is the SSH traffic encrypted?

Yes. While the connection presents as SSH to the client application, all traffic is tunneled through a **WireGuard** connection established using the keys embedded in the token. The `gliderlabs/ssh` wrapper on the server side operates inside this encrypted tunnel.

### Can I use a standard OpenSSH client without installing the Tailcat CLI?

No. The connection requires the Tailcat binary to act as a `ProxyCommand` to establish the WireGuard tunnel using the server-specific token. Standard OpenSSH cannot interpret the ConnBlob format or negotiate the DERP relay connection without the Tailcat proxy intermediary.