# How to Connect to a Tailcat Server: 4 Methods Explained

> Learn how to connect to a Tailcat server using four methods: CLI, Web UI, SSH, or SOCKS5. Access your server easily and securely.

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

---

**You can connect to a Tailcat server using the CLI for command forwarding, the browser-based Web UI via JavaScript bindings, standard SSH clients for SFTP, or any SOCKS5-compatible application.**

Tailcat is a peer-to-peer TCP relay built on Tailscale's DERP network that enables secure connections without requiring public IP addresses. This guide explains how to connect to a Tailcat server using the different front-ends implemented in the `tailscale/tailcat` repository, referencing the actual source code structures that manage the connection lifecycle.

## Understanding Tailcat's Connection Architecture

Before initiating a connection, it helps to understand how Tailcat establishes its peer-to-peer tunnels.

### Ed25519 Key-Derived Addresses

Every Tailcat server generates an **Ed25519 private key**, hashing the public key to produce a human-readable address ending in `.tc` (e.g., `example.tc:23`). This address is stored in the server's `Key` field within the `tailcat.Server` struct defined in [`tailcat.go`](https://github.com/tailscale/tailcat/blob/main/tailcat.go). Clients use this address to locate and authenticate the server.

### DERP Relay and Handshake

Both client and server open a WireGuard-over-DERP tunnel using the `tailcat.Client` struct. The core connection flow involves:

1. Fetching the DERP map from `https://tailcat.dev/derpmap.json` (or a custom `DERPMapURL`)
2. Sending a "Meow" packet handshake request (implemented in [`tailcat/connblob_deprecated.go`](https://github.com/tailscale/tailcat/blob/main/tailcat/connblob_deprecated.go))
3. Receiving a connection string containing the DERP region and unique session identifier
4. Multiplexing logical TCP streams over the single DERP tunnel

## How to Connect Using the CLI

The `tailcat` binary in [`cmd/tailcat/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/cmd/tailcat/tailcat.go) provides direct command forwarding through an encrypted tunnel.

Start a server on the remote machine:

```bash
tailcat -listen

```

The server prints its listen address to stderr (see lines 1523-1524 in [`cmd/tailcat/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/cmd/tailcat/tailcat.go)). For scripting, use the `--json` flag (line 1536) to emit the address in machine-readable format.

Connect from the client and run a command:

```bash
tailcat example.tc:23 curl https://ifconfig.me

```

The CLI creates a tunnel to the server, runs the command locally, and forwards I/O over the Tailcat connection.

## How to Connect via the Web UI

The browser interface uses WebAssembly bindings defined in [`web/main_js.go`](https://github.com/tailscale/tailcat/blob/main/web/main_js.go) to expose the connection logic to JavaScript.

Access the hosted demo at `https://tailcat.dev/` or run the local server:

```bash
tailcat-web

```

The page provides **"Listen"** and **"Dial"** buttons that call the JavaScript globals `tailcatListen` and `tailcatDial`. From the browser console or embedded scripts (as seen in [`web/app.js`](https://github.com/tailscale/tailcat/blob/main/web/app.js) at line 142):

```javascript
const ln = await tailcatListen({ 
  derpMapURL, 
  privateKey, 
  verbose, 
  onConnection 
});

```

This spins up a server or client directly inside the browser for interactive file transfers or remote shell sessions.

## How to Connect Using SSH

Tailcat implements a minimal SSH subsystem in [`tailcat_ssh.go`](https://github.com/tailscale/tailcat/blob/main/tailcat_ssh.go) that supports SFTP and a basic MOTD.

Start the SSH server:

```bash
tailcat -ssh -listen

```

Connect from the client using the built-in SSH client:

```bash
tailcat ssh example.tc:23

```

You will see the server's MOTD: "🐈 Connected via tailcat SSH" (defined at line 30 of [`tailcat_ssh.go`](https://github.com/tailscale/tailcat/blob/main/tailcat_ssh.go)). Note that the server only offers **SFTP** for file transfers, not a full shell environment. Standard `sftp` tools can interact with this subsystem.

## How to Connect via SOCKS5 Proxy

The SOCKS5 proxy mode allows any application to route traffic through the Tailcat tunnel.

Create a local proxy server:

```bash
tailcat socks --listen=0.0.0.0:1080

```

Use any SOCKS5-compatible client. For example, with `curl`:

```bash
curl -x socks5h://localhost:1080 http://ifconfig.me

```

The proxy implementation resides in [`cmd/tailcat/socks.go`](https://github.com/tailscale/tailcat/blob/main/cmd/tailcat/socks.go), with the listener setup occurring in [`cmd/tailcat/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/cmd/tailcat/tailcat.go) at lines 1045-1061. Each TCP stream is forwarded through the Tailcat DERP tunnel to the destination.

## Summary

- **Tailcat servers** advertise Ed25519-derived addresses ending in `.tc`, stored in the `Server.Key` field
- **Four connection methods** are available: CLI (`tailcat <addr>`), Web UI (`tailcatListen`/`tailcatDial`), SSH (`tailcat ssh`), and SOCKS5 (`tailcat socks`)
- **Core connection logic** resides in [`tailcat.go`](https://github.com/tailscale/tailcat/blob/main/tailcat.go), [`tailcat_client.go`](https://github.com/tailscale/tailcat/blob/main/tailcat_client.go), and [`tailcat_server.go`](https://github.com/tailscale/tailcat/blob/main/tailcat_server.go)
- **Handshake mechanism** uses "Meow" packets defined in [`tailcat/connblob_deprecated.go`](https://github.com/tailscale/tailcat/blob/main/tailcat/connblob_deprecated.go) to establish the DERP tunnel

## Frequently Asked Questions

### What address format does Tailcat use for server identification?

Tailcat uses human-readable addresses derived from Ed25519 public key hashes, formatted as `<base32-encoded-key>.tc` with an optional port (e.g., `example.tc:23`). This address is generated by the server and stored in the `Key` field of the `tailcat.Server` struct according to the source code in [`tailcat.go`](https://github.com/tailscale/tailcat/blob/main/tailcat.go).

### How does the initial handshake work between client and server?

The client sends a "listen" or "dial" request encapsulated in a **Meow packet** to initiate the connection. The server responds with a connection string containing the DERP region and unique session identifier. This handshake logic is implemented in [`tailcat/connblob_deprecated.go`](https://github.com/tailscale/tailcat/blob/main/tailcat/connblob_deprecated.go) within the core library, creating the encrypted tunnel over Tailscale's DERP network.

### Can I use standard OpenSSH clients with Tailcat servers?

Yes, but with limitations. The Tailcat SSH subsystem ([`tailcat_ssh.go`](https://github.com/tailscale/tailcat/blob/main/tailcat_ssh.go)) only supports **SFTP** for file transfers and displays a minimal MOTD. You must use the `tailcat ssh <addr>` command rather than the standard `ssh` binary, as the Tailcat client implements the specific protocol handshake required to establish the DERP tunnel before SSH negotiation begins.

### Is the Web UI connection method secure for production use?

The Web UI utilizes the same WireGuard-over-DERP encryption as the CLI, with JavaScript bindings (`tailcatListen` and `tailcatDial` in [`web/main_js.go`](https://github.com/tailscale/tailcat/blob/main/web/main_js.go)) handling cryptographic operations in the browser. However, for production environments requiring automated authentication or integration with existing security tooling, the CLI or SOCKS5 proxy methods are recommended over the browser-based interface.