# Relay connections through a blind relay



Most peers reach each other directly: [hole punching](/p2p/explanation/peer-to-peer-demystified#hole-punching-and-nat-traversal) opens a path through both firewalls and the connection carries on without an intermediary. On some networks it cannot. A **randomizing NAT**—common on corporate and carrier-grade networks—assigns an unpredictable external port per connection, so neither side can tell the other where to dial.

A **blind relay** is the fallback: a third machine that forwards encrypted stream messages between two peers that cannot meet directly. It is "blind" in the same sense as a [blind peer](/pear/explanation/availability-and-blind-peering)—it moves bytes it cannot read. Unlike a blind peer, it stores nothing; it only forwards live connections.

<Callout type="info">
  Since Pear 3.4.0 this is built into the CLI: [`pear blind-relay start`](/pear/reference/pear/cli#pear-blind-relay) runs the relay, and [`--relay <key>`](/pear/reference/pear/cli#relay-flag) points a peer at one.
</Callout>

## Before you start [#before-you-start]

You need a **third machine** that both peers can reach—a VPS or any always-on host with working connectivity. A relay on one of the two peers' own networks defeats the purpose: if that network is the one blocking direct connections, it cannot rescue them.

## Run the relay [#run-the-relay]

On the relay host:

```bash skip="live-relay"
pear blind-relay start
```

It prints a live table. The first row is the one you need:

```text skip="sample-output"
 Public Key:          <relay-key>
 Sessions Accepted:   0
 Sessions Opened:     0
 Sessions Closed:     0
 Sessions Active:     0
 Pairings Requested:  0
 Pairings Matched:    0
 Pairings Pending:    0
 Pairings Active:     0
 Streams Opened:      0
 Streams Closed:      0
 Streams Errors:      0
 Streams Active:      0
```

Copy `<relay-key>`. That is what peers pass to `--relay`.

The relay's key pair is derived from the platform corestore on that machine, so **the key is stable across restarts**—note it down once and reuse it. The process must stay running to relay anything; put it under a service manager for anything long-lived.

<Callout type="tip">
  Only one relay runs per sidecar. Starting a second fails with `Blind relay is already running, cannot start another`.
</Callout>

## Point a peer at the relay [#point-a-peer-at-the-relay]

On each peer that needs relaying, pass the relay's key once:

```bash skip="live-relay"
pear --relay <relay-key> info
```

Any command works—`info` is just a cheap one to run. The point is the flag, not the command.

<Callout type="warn">
  `--relay` registers the relay with the **sidecar**, the shared background process, not with the command you attached it to. That has two consequences worth knowing up front:

  * You only need to pass it **once**. It stays in effect for everything that sidecar does afterwards, so there is no need to add `--relay` to every subsequent command.
  * There is no flag that unsets it. To stop relaying, restart the sidecar with [`pear sidecar shutdown`](/pear/reference/pear/cli#pear-sidecar).
</Callout>

An invalid key is rejected before the command runs:

```text skip="sample-output"
--relay <key> must supply a valid public key
```

## What actually happens next [#what-actually-happens-next]

Registering a relay does **not** push your traffic through it. The swarm keeps connecting directly whenever it can, and consults the relay only when a connection genuinely needs relaying—or when this machine's DHT node is randomized, which is the unpredictable-NAT case hole punching cannot solve.

So on a healthy network you may register a relay and never see it carry a byte. That is the intended behaviour, not a misconfiguration.

## Confirm it is working [#confirm-it-is-working]

Watch the relay's table while the peers connect. Relayed traffic moves these counters:

* **Pairings Requested / Matched** — two peers asked the relay to introduce them, and it matched them by token. A request that never matches means only one side reached the relay.
* **Streams Opened / Active** — forwarding is underway.
* **Streams Errors** — forwarded streams that failed.

`Sessions` count peers connected to the relay itself, so a peer that registered the relay but never needed it shows a session with no pairings.

If the counters stay at zero while two peers fail to connect, check in this order:

1. Both peers registered the **same** relay key—`--relay` on one side only cannot pair.
2. The relay host is reachable from both peers, and `pear blind-relay start` is still running.
3. The peers' sidecars actually picked the flag up. Each sidecar keeps its own relay setting, and it is lost on restart—if a sidecar restarted, pass `--relay` again.

## See also [#see-also]

* [`pear blind-relay` and `--relay` reference](/pear/reference/pear/cli#pear-blind-relay)—every flag and the stats fields.
* [Peer-to-peer, demystified](/p2p/explanation/peer-to-peer-demystified#hole-punching-and-nat-traversal)—why hole punching fails on randomizing NATs.
* [Availability and blind peering](/pear/explanation/availability-and-blind-peering)—the other "blind" service, which keeps data available rather than forwarding connections.
* [Connect two peers by key with HyperDHT](/p2p/how-to/connect-to-peers/connect-two-peers-by-key-with-hyperdht)—the direct-connection path this falls back from.
