How to Test Tailcat Connectivity with `tailcat ping`

Run tailcat ping <addrblob> to send a lightweight discovery ping that reports round-trip latency and confirms whether the connection traverses a DERP relay or uses a direct path.

The tailscale/tailcat repository includes a dedicated subcommand for validating network paths between nodes. When you need to test Tailcat connectivity, the tailcat ping utility offers a reliable method to verify reachability, measure latency, and diagnose whether your traffic requires relay traversal. This command leverages Tailscale's discovery protocol to provide immediate feedback on your mesh network's health.

Understanding the tailcat ping Mechanism

The ping implementation resides in cmd/tailcat/tailcat.go within the clientPingMode function. When executed, the client builds a tailcat.Client instance configured with the DERP map URL and optional authentication keys (lines 68-76). The core logic invokes Client.DiscoPing, which transmits a specially crafted meow packet across the DERP network. The target server responds with a meowed acknowledgment, allowing the client to calculate precise round-trip time and identify the responding endpoint (lines 83-98).

Interpreting tailcat ping Output

The command prints structured results indicating both latency and network path. A typical response follows the format pong in 12.3ms via DERP(2) when traversing a relay, or pong in 1.4ms via 192.0.2.1:12345 when a direct connection is established. This output distinguishes between relayed and direct connectivity, critical for diagnosing NAT traversal behavior.

Running tailcat ping Commands

Basic Connectivity Verification

To perform a standard reachability test, first start a Tailcat server to generate an address blob, then invoke the ping command:


# Start server and capture address

$ tailcat --serve=0 > /tmp/addrblob &
$ ADDRESS=$(cat /tmp/addrblob)

# Test basic connectivity

$ tailcat ping "$ADDRESS"
pong in 9.8ms via DERP(2)

Testing Direct Path Establishment with --until-direct

For scenarios requiring validation of direct connectivity without DERP relays, use the --until-direct flag. This repeatedly sends discovery pings until either a direct path is established or the specified timeout expires:

$ tailcat ping --until-direct --timeout=30s "$ADDRESS"
pong in 1.1ms via 10.0.0.2:12345

This approach is particularly valuable when testing firewall rules or NAT hairpinning configurations.

Automated Testing in the Repository

The tailscale/tailcat codebase includes comprehensive integration tests in cmd/tailcat/ping_test.go (lines 12-41). These tests validate the ping functionality by:

  • Starting a temporary server via e.startServer()
  • Executing the ping command through the test harness using e.cmd(...).CombinedOutput()
  • Asserting that output contains "pong" for basic connectivity
  • Verifying the final line indicates a direct path when testing the --until-direct flag

Run the specific test suite with:

$ go test ./cmd/tailcat -run TestPing
=== RUN   TestPing
--- PASS: TestPing (0.12s)
    --- PASS: TestPing/ping (0.06s)
    --- PASS: TestPing/until_direct (0.06s)
PASS
ok      github.com/tailscale/tailcat/cmd/tailcat   0.13s

Summary

  • The tailcat ping command tests Tailcat connectivity by sending meow discovery packets through the DERP network or direct paths.
  • Successful responses display latency and the specific endpoint (DERP relay ID or direct node address) that answered the ping.
  • Use --until-direct to verify that NAT traversal succeeds and direct connectivity is achievable.
  • The repository's ping_test.go provides automated validation using the newTestEnv infrastructure.

Frequently Asked Questions

What does "via DERP(2)" mean in the ping output?

This indicates the ping traversed a DERP (Designated Encrypted Relay for Packets) relay server with region ID 2. According to the implementation in cmd/tailcat/tailcat.go, this occurs when direct UDP connectivity cannot be established between nodes, forcing traffic through a relay node to ensure connectivity across restrictive NATs or firewalls.

How can I confirm that direct connectivity is working?

Run tailcat ping --until-direct <addrblob>. The command will loop until the output shows a specific IP address and port (e.g., via 10.0.0.2:12345) rather than a DERP identifier. The --timeout flag limits how long the client attempts to establish the direct path before exiting.

What is the difference between tailcat ping and standard ICMP ping?

While ICMP ping tests basic IP reachability using echo requests, tailcat ping specifically tests the Tailcat overlay network. It validates the discovery mechanism (Client.DiscoPing), encryption handshake readiness, and the specific network path (direct or relayed) that Tailcat traffic will actually use between nodes.

Can I use tailcat ping without starting a server manually?

Yes. The repository's test suite in cmd/tailcat/ping_test.go demonstrates automated testing where e.startServer() programmatically launches a temporary server within the test context. For manual testing outside the test suite, you must have a running Tailcat server to generate the address blob required as the ping target.

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 →