How to Connect to a Tailcat Server Using a Token and Port

To connect to a Tailcat server, pass the ConnBlob token as the first argument to the tailcat command, optionally followed by the target port number to access specific services.

Tailcat, an experimental networking tool from the tailscale/tailcat repository, eliminates traditional address resolution by using self-contained ConnBlob tokens that encode all necessary connection metadata. These tokens contain the server’s public key, DERP relay region, and network path information, allowing clients to establish direct connections without fetching additional DERP maps. Understanding how to generate these tokens on the server and parse them on the client is essential for accessing services running on specific ports.

Understanding the ConnBlob Token

A ConnBlob is a self-contained address token that packs all required network details into a single string starting with tc. According to the source code in tailcat.go, the server generates this token via the Server.ConnBlob() method, which serializes the server’s public key and DERP region information into a base64-encoded blob.

When the server starts, it prints this token to stdout (see lines 93-100 in tailcat.go). The token encapsulates:

  • The server’s public key for cryptographic identity
  • DERP relay coordinates for NAT traversal
  • Region metadata for optimal path selection

Because the ConnBlob contains complete connection semantics, clients do not need to perform separate service discovery or DERP map lookups before dialing.

Starting the Server and Generating Tokens

To expose services, start the Tailcat server with the --serve flag followed by the ports you wish to expose. The server automatically generates and displays the ConnBlob token upon initialization.


# Listen on ports 22 and 80, then output the address token

tailcat --serve=22,80

Example output:


tcAeyJzZXJ2ZXJQdWJsaWMiOiAiYWJjZDEyMzQiLCAicmVnaW9uIjpbeyJyZWxheSI6InNkcyJ9XX0=

This token is portable and can be shared with any client authorized to connect. The server handles incoming connections by validating the client’s credentials against the embedded public key within the token itself.

Connecting to a Specific Port

Clients connect by passing the ConnBlob as the first positional argument, followed by the target port number. The client implementation in cmd/tailcat/tailcat.go parses the token using ParseConnBlob, then calls ConnInfo.Expand to resolve the full list of DERP relays before establishing the TCP connection.


# Pipe data to a service listening on port 80 on the server

echo "GET / HTTP/1.1" | tailcat <addrblob> 80

If you omit the port argument, the client connects to a default service. The connection logic handles both direct paths and DERP-relayed paths automatically based on the network conditions encoded in the token.

Using the Built-in SSH Client

For SSH access, use the dedicated ssh subcommand implemented in cmd/tailcat/ssh.go. This command accepts the same ConnBlob token and defaults to port 22 unless specified otherwise.


# SSH into the server using the default SSH port 22

tailcat ssh <addrblob>

The SSH client uses the identical token parsing and connection expansion logic as the standard client, ensuring consistent authentication regardless of which subcommand you invoke.

Resolving Short Tokens

Tailcat supports abbreviated tokens for convenience. To expand a short token into its full, self-contained form programmatically, use the resolve command:

tailcat resolve <short-addrblob>

This outputs the complete ConnBlob with fully embedded DERP details, useful for scripts that need to cache or manipulate the connection parameters directly.

Summary

  • ConnBlob tokens encode the server’s public key, DERP region, and connection metadata in a single tc… string generated by Server.ConnBlob() in tailcat.go.
  • Start servers with --serve=<ports> to automatically generate and display connection tokens.
  • Connect to specific services by passing the token followed by the port number: tailcat <token> <port>.
  • Use tailcat ssh <token> for SSH connections, which leverages the same token-based authentication flow.
  • The client-side logic in cmd/tailcat/tailcat.go uses ParseConnBlob and ConnInfo.Expand to resolve network paths without requiring external DERP map lookups.

Frequently Asked Questions

What information does a ConnBlob token contain?

A ConnBlob contains the server’s public key for identity verification, the DERP relay region for NAT traversal, and additional network metadata required to establish a direct or relayed connection. This self-contained design eliminates the need for clients to fetch DERP maps separately.

Do I need to manually specify DERP servers when connecting?

No. The ConnBlob token generated by Server.ConnBlob() already includes the necessary DERP relay coordinates. When the client parses the token using ParseConnBlob and calls ConnInfo.Expand, it extracts all required routing information automatically.

Can I use the same token to connect to different ports on the same server?

Yes. The same ConnBlob token works for any port exposed by the server via the --serve flag. Simply append the desired port number as the second argument to the tailcat command to route to different services.

What is the difference between tailcat and tailcat ssh?

The standard tailcat <token> <port> command opens a raw TCP connection to the specified port, suitable for HTTP or custom protocols. The tailcat ssh <token> subcommand, defined in cmd/tailcat/ssh.go, initiates an SSH session specifically and defaults to port 22 unless overridden. Both use identical token parsing logic but differ in protocol handling.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →