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 theServer,Client, andConnBlobAPIs.pickregion.go: Implements automatic DERP region selection usingtailscale.com/net/netcheckto find the lowest-latency relay.wire.go: Handles CBOR encoding for the connection token, wrappingtailcfgtypes for compact wire representation.disco.go: A thin wrapper around thetailscale.com/discopackage for endpoint advertising.
Summary
Tailcat demonstrates the reusability of Tailscale’s networking stack by composing these essential components:
- Encryption and Routing:
wgengine,wgcfg, andtypes/keyprovide WireGuard functionality without custom cryptography. - NAT Traversal:
discoandnetmonenable Magicsock-style endpoint discovery and UDP hole punching. - Virtual Networking:
netstackandroutercreate an isolated TCP/IP environment within the process. - Configuration:
tailcfg,netmap, andtsdstandardize network state representation. - Observability:
health,ipnstate, andeventbusintegrate 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →