What Is the Exit-Node Service Type in Tailcat?

The exit-node service type configures Tailcat to operate as a full-mesh Tailscale exit node, forwarding all inbound connections to the host's local network interfaces when you start the service with --serve=exit-node.

The exit-node service type is a core networking mode in the Tailcat repository (tailscale/tailcat) that transforms the process into a bidirectional traffic gateway. When activated, Tailcat advertises itself to the Tailscale network as an exit node capable of routing traffic for any address reachable by the host, enabling other Tailscale clients to obtain internet access or reach internal resources through the Tailcat host's network stack.

How the Exit-Node Service Works in Tailcat

When you invoke Tailcat with the exit-node service, the program diverges from its default single-connection behavior and initializes a persistent server that listens for Tailscale network traffic.

Command-Line Activation

You can activate the exit-node mode using either the flag syntax or the subcommand syntax:


# Using the serve subcommand (recommended)

tailcat serve exit-node

# Using the explicit flag syntax

tailcat --serve=exit-node

According to the source in cmd/tailcat/tailcat.go at line 94, the --serve flag description explicitly lists exit-node as an option to "run an exit node for all addresses." Additional usage examples appear at lines 312 and 487, demonstrating the expected CLI patterns for this service type.

Network Architecture

When operating as an exit node, Tailcat performs three critical functions:

  • Full-Mesh Advertisement: The process registers itself with the Tailscale coordination server as an exit node, making it available to all devices in your tailnet.
  • Traffic Forwarding: All inbound connections from Tailscale clients are forwarded to the host's local network interfaces, allowing access to the broader internet or private subnets.
  • Bidirectional Routing: Unlike the default stdout mode, which handles single connections, the exit-node service maintains a persistent forwarding path for sustained traffic flow.

Implementation Details in the Tailcat Source Code

The exit-node logic is implemented primarily in cmd/tailcat/tailcat.go, with supporting tests verifying the behavior across network conditions.

Service Detection Logic

The main server loop specifically checks for the presence of the exit-node service before falling back to one-shot mode. As implemented at line 1388 in cmd/tailcat/tailcat.go, the code inspects the service list:

// Example pattern from the Tailcat source
if services.Contains("exit-node") {
    // Initialize the exit-node server path
}

This conditional ensures that when exit-node is present, Tailcat skips the stdout-streaming behavior and instead launches the exit-node server initialization routines.

Server Initialization

Once detected, the exit-node startup path executes at lines 1421 and 1464 of cmd/tailcat/tailcat.go. This code path:

  1. Configures the Tailscale node to accept subnet routes and exit-node traffic
  2. Sets up the TCP forwarder that bridges Tailscale connections to the local network stack
  3. Maintains the advertisement to the coordination server, ensuring the node remains discoverable

The implementation ensures that any Tailscale client selecting this node as its exit node will route all non-Tailscale traffic through the Tailcat host, effectively using the host's network connection as a proxy.

Practical Configuration Examples

To deploy Tailcat as an exit node in production environments, use the following patterns:


# Start as exit node with default settings

tailcat serve exit-node

# Run as exit node with explicit backend binding

tailcat --serve=exit-node --backend=100.64.0.1:8080

For systemd integration, create a service that invokes the exit-node mode on boot:


# /etc/systemd/system/tailcat-exit-node.service

[Unit]
Description=Tailcat Exit Node
After=network.target

[Service]
ExecStart=/usr/local/bin/tailcat serve exit-node
Restart=always

[Install]
WantedBy=multi-user.target

Testing and Validation

The Tailcat repository includes comprehensive tests that verify exit-node functionality:

  • cmd/tailcat/serve_test.go: Validates that --serve=exit-node correctly initializes the server without errors and properly registers the service type.
  • cmd/tailcat/forward_test.go: Verifies that traffic forwarding through an exit-node target functions correctly, ensuring packets reach their intended destinations via the host's network stack.
  • cmd/tailcat/ssh.go: Demonstrates interaction patterns between SSH connections and exit-node mode, confirming that the service type influences how other protocols (like SSH) are handled when the server operates as a network gateway.

These tests ensure that when services.Contains("exit-node") evaluates to true, the resulting server configuration correctly handles both ingress and egress traffic flows.

Summary

  • The exit-node service type in Tailcat transforms the process into a Tailscale exit node capable of routing all client traffic through the host's network interfaces.
  • Activation requires either tailcat serve exit-node or tailcat --serve=exit-node, as defined in cmd/tailcat/tailcat.go (lines 94, 312, 487).
  • The implementation checks for this service at line 1388 to bypass single-connection mode and initializes the exit-node server at lines 1421 and 1464.
  • When active, the node advertises itself to the full Tailscale mesh, allowing any client to select it as their internet gateway or route to internal resources.

Frequently Asked Questions

How do I verify that Tailcat is running correctly as an exit node?

Check the Tailscale admin console to confirm the device appears as an exit node option, or run tailcat serve exit-node with verbose logging enabled. According to cmd/tailcat/serve_test.go, successful initialization shows no startup errors and the process remains running rather than exiting after a single connection.

Can I run multiple service types alongside exit-node in Tailcat?

The source code in cmd/tailcat/tailcat.go processes the service list as a collection, checking services.Contains("exit-node") among other options. While the exit-node mode primarily focuses on full-network forwarding, you should verify compatibility with other specific service combinations by consulting the server initialization logic at lines 1388-1464.

What is the difference between exit-node and standard port forwarding in Tailcat?

Standard Tailcat operation accepts a single connection and streams data to stdout, suitable for one-off debugging or specific port tunnels. The exit-node service, conversely, creates a persistent server that handles all inbound connections from the Tailscale network, forwarding them to the host's local interfaces to provide comprehensive network access rather than single-port exposure.

Does the exit-node service require special permissions on the host system?

Yes, operating as an exit node typically requires elevated privileges to bind to low-numbered ports and to configure the host's networking stack for IP forwarding. The implementation in cmd/tailcat/tailcat.go assumes the process has sufficient permissions to advertise subnet routes and accept traffic destined for arbitrary destinations.

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 →