How Tailcat Achieves Control-Plane-Free WireGuard Tunneling

Tailcat establishes direct WireGuard tunnels without any external control plane by embedding all necessary configuration—including public keys and DERP relay addresses—inside a compact CBOR blob exchanged during the initial HTTPS handshake.

Tailcat is an experimental project from Tailscale that demonstrates how to create secure WireGuard connections without relying on the traditional Tailscale coordination server. Unlike standard Tailscale deployments that require a control plane to distribute keys and network topology, control-plane-free WireGuard tunneling embeds the entire connection metadata into a self-contained payload exchanged out-of-band.

The Self-Contained Configuration Architecture

Traditional WireGuard deployments rely on external services to coordinate public key exchange and endpoint discovery. Tailcat eliminates this dependency by compressing all required state into a single CBOR-encoded blob that travels over the initial HTTPS connection.

Embedding WireGuard State in CBOR

The architecture centers on the ConnInfo structure, which encapsulates the server's WireGuard public key, discovery (disco) key, and DERP region information. According to the source code in tailcat.go, this structure is serialized using custom wire types defined in wire.go, including wireConnInfo, wireRegion, and wireNode. The struct tags use single-character CBOR field names to minimize payload size.

When a client connects, the server returns this blob via an HTTP response—typically from the /info endpoint implemented in the ServeHTTP method. No subsequent coordination with an external control plane occurs after this initial exchange.

Server-Side Implementation: Generating and Encoding

The server bootstrap process involves two critical phases: cryptographic key generation and compact serialization.

Key Generation Without External Coordination

In tailcat.go, the initLocked function generates the server's WireGuard private/public key pair alongside a separate disco key pair used for path discovery. These keys populate the ConnInfo structure. As noted in tailcat_ssh.go, "Authentication is not required — the WireGuard tunnel provides identity," eliminating the need for pre-shared credentials or OAuth flows with a coordination server.

Compact Wire Format Serialization

The conversion logic resides in wire.go, which provides mapping functions like wireRegionOf and (*wireRegion).derpRegion to transform internal structures into portable wire formats. The CBOR encoding ensures the payload remains small enough to transmit inline within an HTTP response header or body, avoiding the latency of multiple round-trips to a configuration service.

Client-Side Implementation: Decoding and Tunnel Establishment

The client receives the configuration blob and configures its local WireGuard engine without querying external services.

Parsing the Connection Blob

The client retrieves the CBOR payload from the server's /info endpoint and processes it through ParseConnBlobRaw (found in tailcat.go). This function decodes the compact binary format back into a ConnInfo structure, extracting the server's public key, disco key, and DERP endpoint addresses.

Local Engine Configuration

With the parsed ConnInfo, the client invokes wgengine.Engine.SetPeerConfigFunc (implemented around line 1319 in tailcat.go) to install a per-peer configuration source. This callback supplies the WireGuard engine with the server's public key and DERP relay address dynamically:

// Simplified from tailcat.go
cfgFunc := func() *wgengine.PeerConfig {
    return &wgengine.PeerConfig{
        PublicKey:   ci.ServerPublic,
        Endpoints:   []netaddr.IPPort{ci.DERPEndpoint},
        DiscoKey:    ci.ServerDiscoPublic,
    }
}
wgEngine.SetPeerConfigFunc(cfgFunc)

The WireGuard engine then performs the standard cryptographic handshake directly with the server, using the embedded DERP relay for NAT traversal. Because the DERP region information travels inside the initial blob, no additional discovery step or control plane query occurs.

Eliminating Control Plane Dependencies

The comment at line 17 in tailcat.go explicitly states the design goal: "WireGuard tunnel with no Tailscale account or coordination server required." By embedding the full network topology—including relay addresses and cryptographic identities—within the CBOR payload, Tailcat removes the traditional requirement for a persistent connection to a coordination server.

This approach works because the HTTPS handshake that delivers the CBOR blob provides the necessary encryption and authentication for the initial key exchange. Once both peers possess each other's public keys and DERP coordinates, the WireGuard protocol operates autonomously, handling key rotation and session management without external state management.

Summary

  • CBOR encapsulation: All WireGuard configuration data is compressed into a compact binary blob using one-character field names defined in wire.go.
  • In-band key distribution: The server generates keys locally in initLocked and transmits them via the /info HTTP endpoint, eliminating the need for a separate control plane.
  • Local engine configuration: Clients configure their WireGuard engines using SetPeerConfigFunc with data from ParseConnBlobRaw, enabling tunnel establishment without external coordination.
  • Zero external dependencies: The architecture requires no Tailscale account, no OAuth flows, and no persistent connection to a coordination server after the initial HTTPS exchange.

Frequently Asked Questions

How does Tailcat handle NAT traversal without a control plane?

Tailcat embeds DERP (Designated Encrypted Relay for Packets) region information directly within the CBOR configuration blob. Because both the client and server receive each other's DERP endpoint addresses during the initial HTTPS handshake, they can route traffic through Tailscale's DERP relays immediately without querying a separate discovery service.

What makes CBOR better than JSON for this use case?

CBOR provides a binary encoding that is significantly more compact than JSON while maintaining schema flexibility. The wire.go implementation uses single-character field keys to minimize payload size, ensuring the configuration blob remains small enough to transmit efficiently within an HTTP response without fragmentation.

Can Tailcat work without any internet access at all?

No—Tailcat requires network connectivity to exchange the initial CBOR blob (typically over HTTPS) and to reach the DERP relays embedded in the configuration. However, once the blob is exchanged, the WireGuard tunnel operates independently without requiring access to Tailscale's coordination servers or the public internet if both peers are on the same local network.

Why doesn't Tailcat require traditional authentication?

As stated in tailcat_ssh.go, "Authentication is not required — the WireGuard tunnel provides identity." The cryptographic properties of WireGuard's key exchange provide mutual authentication; if a client can successfully complete the Noise protocol handshake with the server using the public keys exchanged in the CBOR blob, identity is cryptographically verified without requiring passwords, certificates, or OAuth tokens.

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 →