Direct and relayed connections
How two devices find a path to each other through NATs and firewalls, when traffic goes through a relay, and how to see which path a connection uses.
Updated · ·By Ivan Vyshniak
This page changes with your operating system.
Traffic between two devices takes one of two paths:
- Direct: UDP packets straight between the devices, through any NATs and firewalls in between. Lowest latency.
- Relayed: through one of Peerlify's relays, over TCP. Works almost anywhere, with extra latency.
Both paths carry the same end-to-end encrypted packets. A relay can't read them.
How a connection is set up
- Start on the relay. The first packets to a peer always go through a relay, so a connection works within a moment of the first packet.
- Look for a direct path in parallel. Each device collects the addresses at which it might be reachable (see below) and sends them to the peer inside the encrypted session. Both devices then send probes to each other's addresses every second: for the first 30 seconds, and after that for as long as traffic keeps flowing between them. Sending at the same time from both sides lets the probes open NAT and firewall mappings for each other ("hole punching").
- Switch when a path works. Once a probe is answered, traffic moves to the direct path. The relay connection stays open as a fallback.
- Keep it alive. On a direct path, the devices exchange a keep-alive every 5 seconds. If keep-alives go unanswered for 20 seconds, traffic falls back to the relay and the search for a direct path starts again with the next packet.
- Peer goes quiet. Connected devices exchange a short status message every 5 seconds, even without traffic. If nothing at all arrives from a peer for 30 seconds, for example because it went offline, its connection is closed. The next packet starts again at step 1.
Running peerlify ping <peer> also starts the search for a direct path, which is a quick way to establish one.
Addresses a device offers
In order of preference:
| Kind | Example |
|---|---|
| A global IPv6 address of the device | [2001:db8::1a]:62713 |
| A LAN address | 192.168.1.20:62713 |
| A public address mapped by the router through UPnP, NAT-PMP or PCP | 198.51.100.7:62713 |
| The public address seen by the relay's STUN service (UDP 3478) | 198.51.100.7:41022 |
The device asks the router for a port mapping automatically, where the router allows it. All direct traffic uses one local UDP port, chosen at random when the service starts (or fixed with TapClient:Relay:LocalUdpPort; see Client configuration).
When a direct path isn't possible
- Symmetric NAT. Some NATs, common on mobile carriers and some corporate networks, give every destination a different public port. Peerlify doesn't currently traverse these, so a pair where one side is behind such a NAT normally stays on the relay.
- Outbound UDP blocked. If a network blocks outbound UDP, all traffic uses the relay.
- HTTP proxy only. Relays are reached over plain TCP connections, not through HTTP proxies. A network where all traffic must go through a proxy can't carry Peerlify traffic.
A relayed connection is fully functional. It just adds the round trip to the relay.
Relays
Devices connect to relays over TCP, trying port 5879 first, then 443, then 80, and using the first that works. The connection is wrapped in TLS so that firewalls treat it like ordinary web traffic. The TLS layer is not what protects your data; the end-to-end encryption inside it is.
Home relay
Each device picks one relay as its home relay: the relay other devices use to reach it.
- Every 25 seconds, the device measures the connection time to each relay. It ranks relays by the best measurement over the last 5 minutes.
- It moves to a faster relay only if that relay is at least 10 ms and more than 1.5 times faster than the current one. This keeps it from flapping between relays on a jittery network.
- Among relays that are about equally fast, devices spread out over the relays rather than all choosing the same one.
- It moves immediately if it has no home relay yet, if its relay is removed from service, or if its relay has been unreachable for about 5 minutes.
When sending to a peer through a relay, a device prefers the relay that peer last used to reach it, then the peer's home relay, and finally its own home relay.
See which path is in use
peerlify list peers -s shows each peer's current state:
build-server.k3x9q2m7pa.peerlify.net (100.100.0.12) - p2p (198.51.100.23:41641)
prod-db.k3x9q2m7pa.peerlify.net (100.100.0.15) - ERPFServer (203.0.113.10:5879)p2p means direct; ERPFServer means relayed; connecting means the encrypted session isn't up yet; disconnected means there's no connection right now. In peerlify telemetry --json, the relayed state is erpf_server. peerlify ping shows the path of each reply:
pong from build-server.k3x9q2m7pa.peerlify.net (100.100.0.12) via 198.51.100.23:41641 in 14.7ms
pong from prod-db.k3x9q2m7pa.peerlify.net (100.100.0.15) via RELAY(203.0.113.10:5879) in 67.8mspeerlify telemetry shows your home relay, the addresses your device offers, and per-peer state, round-trip time and number of candidate addresses. For a script, use --json:
peerlify telemetry --json | ConvertFrom-Json | Select-Object -ExpandProperty peerspeerlify telemetry --json | jq '.peers[] | {nameInNetwork, state, transportEndpoint, roundTripTimeMs}'peerlify telemetry --json | jq '.peers[] | {nameInNetwork, state, transportEndpoint, roundTripTimeMs}'On Business and Enterprise plans, the console's activity logs also record whether each flow was direct or relayed.
What happens when things change
| Event | What the client does |
|---|---|
| The network changes (Wi-Fi to Ethernet, new IP address) | Rediscovers its addresses, reconnects to relays and looks for direct paths again. Encrypted sessions continue. |
| A peer's service restarts | Notices it can't decrypt the peer's packets and sets up a new session, within a few seconds. |
| A relay goes down | Reconnects with increasing delays (1 to 30 seconds), and reaches peers through other relays meanwhile. |
| The Mac wakes from sleep | Refreshes its connections straight away. On Windows and Linux, recovery after sleep relies on the network-change events and time-outs above. |
| The control plane is unreachable | Keeps working with the peers and rules it already has. See How Peerlify works. |