Relay Servers and NAT Traversal
Most devices live behind NAT routers that block incoming connections. Syncthing solves this with two mechanisms: NAT traversal (hole-punching via QUIC/UTP) and relay servers as a fallback.
Understand the performance cost of relay connections and know when to configure a direct port forward instead to keep sync fast.
| Connection Type | Speed | Latency | Privacy | When Used |
|---|---|---|---|---|
| Direct TCP (port 22000) | Fastest | Lowest | P2P encrypted | Both peers publicly reachable |
| QUIC NAT traversal | Fast | Low | P2P encrypted | Both peers behind NAT, traversal succeeds |
| Relay (relays.syncthing.net) | Slowest | Highest | Encrypted, relay sees metadata | All direct attempts fail |
Connection Negotiation Flow
flowchart TD
A[Device A wants to sync with Device B] --> B[Try direct TCP on port 22000]
B --> C{Success?}
C -- Yes --> G[Direct P2P sync — fastest]
C -- No --> D[Try QUIC NAT hole-punch]
D --> E{Success?}
E -- Yes --> G
E -- No --> F[Fall back to Relay server]
F --> H[Relay-mediated sync — slowest but works]
You can see the active connection type in the GUI under each device's status: Direct, Relayed, or Disconnected.
Checking Connection Type from Logs
# Watch connection events
journalctl --user -u syncthing -f | grep -E "Connected|relay|direct"
# Example output:
# INFO: Connected to K3X2R... at tcp://203.0.113.45:22000 (direct)
# INFO: Connected to K3X2R... at relay://relay.example.com:22067 (relayed)
Enabling/Disabling Relays
Relays are enabled by default. On a VPS with a public IP, disable relays and use a direct port forward instead:
<options>
<relaysEnabled>false</relaysEnabled>
</options>
To keep relays but prefer direct connections:
<options>
<relaysEnabled>true</relaysEnabled>
<!-- Relay connection rate limit — prevents relay abuse -->
<relayReconnectIntervalM>10</relayReconnectIntervalM>
</options>
Running a Self-Hosted Relay
For organizations behind strict firewalls or wanting full control:
# Install strelaysrv
go install github.com/syncthing/syncthing/cmd/strelaysrv@latest
# Run relay on port 22067 (data) and 22070 (status)
strelaysrv -listen ":22067" -status-srv ":22070"
# Get the relay URI (needed for clients)
# Output: relay://YOUR.SERVER.IP:22067/?id=DEVICE_ID&pingInterval=60s&networkTimeout=2m0s
In each client's config.xml:
<options>
<relayServer>relay://YOUR.SERVER.IP:22067/?id=DEVICE_ID</relayServer>
</options>
Self-hosted relays require TCP ports 22067 and 22070 open in your firewall. The public Syncthing relay pool at relays.syncthing.net is used by default and is rate-limited per device for fairness.
NAT Traversal with a VPS Port Forward
The cleanest approach for a server with a public IP: open port 22000 and let Syncthing establish direct connections without relays.
# UFW
sudo ufw allow 22000/tcp
sudo ufw allow 22000/udp # for QUIC
sudo ufw reload
# iptables
sudo iptables -A INPUT -p tcp --dport 22000 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 22000 -j ACCEPT
Verify Syncthing is listening:
ss -tlnp | grep 22000
ss -ulnp | grep 22000
Troubleshooting Matrix
| Symptom | Cause | Fix |
|---|---|---|
| Always "Relayed" even with public VPS | Port 22000 not open | ufw allow 22000/tcp udp |
| Relay connection very slow | Large file sets through community relays | Host your own relay or use direct connection |
| "No relay found" error | All relays unreachable | Check DNS and HTTPS to relays.syncthing.net |
| QUIC not working | UDP 22000 blocked | Allow UDP 22000 in firewall |