Core Tailscale Components Reused by Tailcat: Architecture Guide

Tailcat composes production-grade Tailscale packages—including wgengine, disco, netstack, and tailcfg—to deliver WireGuard-encrypted networking, Magicsock-style NAT traversal, and DERP relay functionality without requiring an external control plane.

Tailcat is an experimental networking tool within the tailscale/tailcat repository that demonstrates how to build a lightweight, encrypted data-plane by importing core Tailscale components. Instead of re-implementing cryptographic tunnels or NAT traversal logic, the project assembles existing high-performance packages from the Tailscale Go module to create a "control-plane-free" node that operates solely via compact connection tokens.

WireGuard Engine and Cryptographic Foundation

At the heart of Tailcat’s encryption layer sits the same userspace WireGuard implementation that powers the standard Tailscale client.

Userspace WireGuard Engine (wgengine)

The tailscale.com/wgengine package provides the packet encryption engine responsible for routing and WireGuard key management. In tailcat.go lines 82–86, the engine is initialized to handle all cryptographic operations. This package includes several critical sub-components:

  • wgengine/netstack (lines 84–86): Supplies an in-process TCP/IP stack that creates a virtual network interface without requiring root privileges or kernel modules.
  • wgengine/router (lines 85–86): Forwards traffic between the virtual netstack and the host network, managing route tables dynamically.
  • wgengine/filter (lines 86–87): Implements a packet filter that restricts inbound ports as a defense-in-depth security measure.
  • wgengine/wgcfg (lines 86–87): Defines configuration structures for WireGuard keys and network addresses.

Cryptographic Identity and Logging

Tailcat uses strongly-typed key structures from tailscale.com/types/key (lines 76–77) to manage node and discovery (disco) public/private key pairs. For observability, it adopts the minimal Logf interface from tailscale.com/types/logger (lines 77–78), ensuring consistent logging across all subsystems.

Magicsock-Style Discovery and NAT Traversal

To establish direct connections through firewalls and NATs, Tailcat reuses Tailscale’s proven endpoint discovery mechanisms.

Discovery Protocol (disco)

The tailscale.com/disco package (lines 63–66) provides the "meow" handshake and endpoint advertising logic originally developed for Magicsock. This enables Tailcat to perform UDP hole punching and STUN-based endpoint discovery automatically.

Network Monitoring (netmon)

Complementing the disco layer, tailscale.com/net/netmon (lines 69–70) tracks local UDP endpoints and reacts to interface changes. This component monitors STUN responses and network topology shifts, triggering endpoint re-advertisement when a host moves between networks.

Virtual Network Stack and Traffic Control

Tailcat runs a complete TCP/IP stack entirely in userspace, eliminating the need for external network configuration.

In-Process TCP/IP Implementation

The netstack package imported at lines 84–86 allows Tailcat to expose TCP listeners and SSH servers without binding to host ports directly. This virtual interface is bridged to the physical network via the wgengine/router component, which handles packet forwarding between the netstack and the host.

Packet Filtering and Security

The wgengine/filter package (lines 86–87) enforces port-level access controls. By default, Tailcat uses this filter to limit which inbound ports a client may access, providing security-by-default even within the encrypted mesh.

Control Plane Types and Network State

Despite operating without a traditional control plane, Tailcat relies on Tailscale’s standard type definitions to describe network topology and configuration.

Network Map and DERP Configuration

The tailscale.com/tailcfg package (lines 73–75) defines types for DERP regions, node descriptions, and the overall network map. Tailcat uses tailscale.com/types/netmap (lines 78–79) to represent the local node and its peer relationships in memory, maintaining compatibility with Tailscale’s standard network map format.

System Dependency Container (tsd)

All subsystems are coordinated through tailscale.com/tsd (lines 71–73), the Tailscale system-dependency container. This container holds references to the engine, netstack, DNS resolver, and health monitors, providing a unified lifecycle management layer for the application.

Observability and System Integration

Tailcat mirrors the status reporting capabilities of the standard Tailscale client through shared interfaces.

Health Tracking and Status Reporting

The tailscale.com/health package (lines 65–66) integrates with Tailscale’s diagnostic system, while tailscale.com/ipn and ipn/ipnstate (lines 66–68) provide the same status structures used by the regular client. The tailscale.com/util/eventbus (lines 80–81) propagates status updates between subsystems asynchronously.

Dialing and DNS Resolution

For outbound connectivity, tailscale.com/net/tsdial (lines 48–49) provides a dialer that can route traffic either through the in-process netstack or directly over UDP. Name resolution inside the virtual network is handled by tailscale.com/net/dns (lines 70–71), which manages the DNS configuration for the netstack.

Utilities and Feature Flags

Supporting functionality includes tailscale.com/net/netns (lines 71–72) for Linux-specific networking isolation, tailscale.com/envknob (lines 16–17) for runtime feature flags like TS_DEBUG_CONNBLOB, and tailscale.com/util/mak (lines 81–82) for efficient map and slice manipulations when building peer lists.

Practical Implementation: Server and Client Examples

The following examples demonstrate how Tailcat assembles these components to create encrypted connections using only a connection token.

Starting a Tailcat Server

This server uses the WireGuard engine, netstack, and disco components to accept encrypted connections and expose an SSH listener on port 22:

package main

import (
	"log"
	"net"

	"github.com/tailscale/tailcat"
)

func main() {
	srv := &tailcat.Server{
		// Use an automatically generated key
		Key: tailcat.key.NodePrivate{},
		// Listen on the default DERP region (auto-detected)
		RegionID: -1,
		// Expose an SSH server (no authentication)
		OnTCP: func(port uint16) func(net.Conn) {
			if port == 22 {
				return func(c net.Conn) {
					// Tailcat provides a minimal SSH implementation
					// For brevity we just close the connection
					c.Close()
				}
			}
			return nil
		},
	}
	if err := srv.Start(); err != nil {
		log.Fatalf("server start: %v", err)
	}
	log.Printf("Tailcat server ready – token: %s", srv.ConnBlob())
	select {} // block forever
}

Connecting a Tailcat Client

The client uses the tsdial package and WireGuard engine to connect via the token generated above:

package main

import (
	"log"

	"github.com/tailscale/tailcat"
)

func main() {
	// Token obtained from the server’s ConnBlob() call
	const token = "tc..."

	client := tailcat.NewClient(tailcat.ConnBlob(token))

	// Optional: run a simple TCP echo test
	if err := client.DialTCPPort(8000).Write([]byte("hello")); err != nil {
		log.Fatalf("dial: %v", err)
	}
	log.Println("connected and sent data")
}

Key Source Files

Understanding the file structure reveals how these components are glued together:

  • tailcat.go: The central library (lines 16–87) that imports all Tailscale packages and exposes the Server, Client, and ConnBlob APIs.
  • pickregion.go: Implements automatic DERP region selection using tailscale.com/net/netcheck to find the lowest-latency relay.
  • wire.go: Handles CBOR encoding for the connection token, wrapping tailcfg types for compact wire representation.
  • disco.go: A thin wrapper around the tailscale.com/disco package for endpoint advertising.

Summary

Tailcat demonstrates the reusability of Tailscale’s networking stack by composing these essential components:

  • Encryption and Routing: wgengine, wgcfg, and types/key provide WireGuard functionality without custom cryptography.
  • NAT Traversal: disco and netmon enable Magicsock-style endpoint discovery and UDP hole punching.
  • Virtual Networking: netstack and router create an isolated TCP/IP environment within the process.
  • Configuration: tailcfg, netmap, and tsd standardize network state representation.
  • Observability: health, ipnstate, and eventbus integrate with Tailscale’s monitoring ecosystem.

By leveraging these packages, Tailcat achieves the same security guarantees as the standard Tailscale client—WireGuard encryption, automatic NAT traversal, and DERP fallback—while remaining a compact, self-contained binary.

Frequently Asked Questions

What is the primary difference between Tailcat and the standard Tailscale client?

Tailcat operates without a centralized control plane or coordination server. While it reuses the same core Tailscale components for encryption and networking (such as wgengine and disco), it establishes connections using a pre-shared connection token (ConnBlob) rather than fetching a network map from Tailscale's control servers. This makes Tailcat suitable for ephemeral, token-based peer connections.

How does Tailcat handle NAT traversal without a control plane?

Tailcat imports the tailscale.com/disco package to perform the standard Magicsock discovery handshake. The disco package (referenced in tailcat.go lines 63–66) advertises endpoints via STUN and attempts direct UDP paths between peers. If direct connection fails, Tailcat falls back to DERP relays, using the region selection logic in pickregion.go to choose the nearest relay automatically.

Which Tailscale package provides the TCP/IP stack for Tailcat?

The in-process TCP/IP stack comes from tailscale.com/wgengine/netstack, imported at lines 84–86 of tailcat.go. This package implements a full network stack in userspace, allowing Tailcat to accept TCP connections and handle DNS resolution internally without requiring root access or TUN device configuration on the host.

Can Tailcat be used in production environments?

Tailcat is currently an experimental demonstration of how to compose Tailscale libraries. While it uses production-grade packages like wgengine and netstack that power millions of Tailscale connections, the specific orchestration in tailcat.go lacks the comprehensive testing, failover logic, and multi-platform support of the official client. It serves best as a reference architecture for building custom Tailscale-powered tools.

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 →