What Is the Meow Protocol in Tailcat? Complete Technical Guide

The Meow protocol is a lightweight, custom bootstrap mechanism implemented in the Tailcat repository that establishes WireGuard peer relationships over DERP connections, distinguished by a four-byte magic prefix [m e o w] and simple ping-pong message exchange to register clients and confirm peer establishment.

The Meow protocol provides the foundational discovery layer for Tailcat, enabling clients to announce their public keys to the server and receive acknowledgment before initiating standard WireGuard handshakes. Unlike traditional discovery mechanisms, this protocol operates directly on Tailscale's DERP relay infrastructure, allowing peer registration even when both endpoints lack direct UDP connectivity.

Meow Protocol Packet Structure

The Meow protocol defines a minimal binary format optimized for embedding within DERP datagrams. As implemented in main/disco.go, each packet begins with a distinctive signature that distinguishes it from other discovery traffic.

Magic Prefix and Message Types

Every Meow packet starts with a four-byte magic prefix defined in main/disco.go lines 15-18 as the byte sequence [m e o w]. Immediately following this prefix, a single byte identifies the message type:

  • meowTypePing (0x01): Sent from client to server to initiate registration
  • meowTypePong (0x02): Sent from server to client as acknowledgment

These constants are defined in main/disco.go lines 20-23.

Payload Format

For MeowPing messages (client-to-server), the payload consists of two consecutive 32-byte raw key values:

  1. The client's NodePublic key
  2. The client's DiscoPublic key

The EncodeMeowPing function in main/disco.go (lines 30-38) serializes these keys directly into the packet buffer following the magic prefix and type byte. The server responds with a Meowed packet, which contains only the magic prefix and the meowTypePong byte (see EncodeMeowed in lines 41-46), providing a deterministic acknowledgment that the peer registration succeeded.

Server-Side Peer Registration

The server processes incoming Meow packets through the (*locoBackend).onMeow method defined in main/tailcat.go (lines 56-60). This handler implements the full lifecycle of peer admission and network configuration.

Validation and Client Filtering

Upon receiving a valid MeowPing, the server first validates the source against an allowedClients authorization list. If the client passes authorization checks, the server constructs a new tailcfg.Node entry containing the parsed public keys and stores it in the internal b.clients map (lines 71-84).

Network Map Distribution

After peer registration, the server immediately constructs a fresh netmap.NetworkMap containing both the server node and all registered peers. This network map is distributed to two critical subsystems:

  1. MagicSock: Updated via mc.SetNetworkMap to establish DERP routing paths
  2. Netstack: Updated via b.sys.Netstack.Get().UpdateNetstackIPs to configure internal IP addressing

This dual update ensures the new peer becomes reachable through both the DERP relay and the virtual network interface.

Sending the Meowed Acknowledgment

Once the peer is fully registered in the network map, the server transmits the Meowed acknowledgment back to the client. As shown around line 429 in main/tailcat.go, the server calls mc.SendDERPPacketTo(src, regionID, EncodeMeowed()) to deliver the pong response through the same DERP region where the ping arrived.

Client-Side Implementation

Clients initiate the WireGuard bootstrap sequence by constructing and transmitting a MeowPing packet, then monitoring the DERP connection for the server's response.

Encoding and Sending MeowPing

The client creates the bootstrap packet using EncodeMeowPing(nodeKey, discoKey) from main/disco.go (lines 30-38). This function serializes the client's node and disco public keys into the standard Meow format. The resulting byte slice is transmitted as a raw DERP packet through the MagicSock layer:

// Build the ping
ping := tailcat.EncodeMeowPing(myNodePublic, myDiscoPublic)

// Send as raw DERP packet
magicSock.SendDERPPacket(remoteAddr, ping)

Receiving the Meowed Response

After transmission, the client blocks on the DERP connection until it receives a valid Meowed packet. The IsMeowedPacket helper function in main/disco.go (lines 64-67) validates the four-byte magic prefix and message type:

// Block until we see a Meowed packet
buf := make([]byte, 1500)
n, _, _ := conn.ReadFrom(buf)
if tailcat.IsMeowedPacket(buf[:n]) {
    // Meowed received – safe to start WireGuard handshake
}

Receipt of this acknowledgment confirms that the server has registered the peer and populated the network map, allowing the client to proceed with standard WireGuard key exchange.

Protocol Detection Helpers

Tailcat provides utility functions to distinguish Meow traffic from other DERP-bound packets without full parsing. The IsMeowPacket function in main/disco.go (lines 25-28) performs a fast four-byte prefix check against the meowMagic constant. Similarly, IsMeowedPacket validates server responses (lines 64-67). These predicates enable efficient packet filtering in the DERP handling pipeline defined in main/wire.go, ensuring Meow packets route to the specialized onMeow handler while other traffic proceeds to standard WireGuard processing.

Summary

  • The Meow protocol uses a four-byte magic prefix [m e o w] to identify bootstrap packets within DERP streams.
  • MeowPing messages carry 32-byte NodePublic and DiscoPublic keys from client to server, initiating peer registration.
  • The server validates clients against allowedClients, registers them in the internal node map, and broadcasts updated network configurations to MagicSock and Netstack.
  • Meowed packets (type 0x02) provide deterministic acknowledgment that peer registration succeeded and WireGuard initialization can proceed.
  • Helper functions IsMeowPacket and IsMeowedPacket in main/disco.go enable zero-copy packet classification before full parsing.

Frequently Asked Questions

How does the Meow protocol differ from standard WireGuard handshake?

The Meow protocol operates at the discovery layer rather than the cryptographic layer. While WireGuard handles key exchange and session establishment, Meow solves the prerequisite problem of how a client announces its existence and public keys to the server when direct UDP connectivity may not exist. According to the Tailcat source code, Meow packets travel over DERP relays (defined in main/wire.go), allowing bootstrap registration through NATs and firewalls that would block standard WireGuard UDP packets.

What security checks does the server perform when processing a MeowPing?

The server implements authorization through the allowedClients check within (*locoBackend).onMeow (main/tailcat.go, lines 56-60). Before creating a tailcfg.Node entry or updating the network map, the server validates that the connecting public key appears in the authorized client list. This prevents unauthorized nodes from injecting themselves into the mesh network during the bootstrap phase.

Can the Meow protocol handle multiple concurrent registration requests?

Yes. The implementation in main/tailcat.go uses the b.clients map (lines 71-84) to store peer state, and the onMeow handler acquires appropriate locks (implied by the backend structure) before modifying shared state. The server constructs a complete netmap.NetworkMap for each successful registration, ensuring all connected peers receive updated routing information through mc.SetNetworkMap calls, supporting dynamic mesh growth without requiring restarts.

What happens if a client never receives the Meowed acknowledgment?

Without receiving a valid Meowed packet validated by IsMeowedPacket (main/disco.go, lines 64-67), the client cannot confirm that the server has registered its peer entry. The client would typically retry the MeowPing transmission or fail to establish the WireGuard tunnel, as the server's network map would not include the necessary peer configuration for routing packets back to the client.

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 →