relay·ssh

SSH into a Pi behind CGNAT

Behind carrier-grade NAT, port forwarding cannot work: the public IP on your router belongs to your ISP and is shared with hundreds of other customers. The fix is to turn the connection around. The Pi opens an outbound tunnel to a relay, and you SSH to the relay. This page shows how to tell whether you are behind CGNAT, and then how to get in.

Check whether you are behind CGNAT

Open your router's status page and note its WAN address. Then, from any machine on the same network, ask the internet what address it sees:

sh
curl -4 ifconfig.me

You are behind CGNAT if either of these is true:

  • The router's WAN address is between 100.64.0.0 and 100.127.255.255. That range is reserved for carrier-grade NAT.
  • The router's WAN address and the curl result are different. The router sits behind a second layer of NAT that you do not control.

A WAN address in 10.x.x.x or 192.168.x.x means the same thing. If the two addresses match and are public, you are not behind CGNAT, and a forwarded port would work — though you may still not want one.

Why port forwarding cannot help

A forwarding rule on your router says "send inbound port 22 to the Pi". But inbound traffic for that public IP arrives at your ISP's NAT first, and the ISP has no rule for it. The packet is dropped before your router ever sees it. Dynamic DNS does not help either: it publishes an address that nobody can connect to. Some ISPs sell a public IP as an add-on; many will not offer one at any price. Mobile carriers never do.

Outbound connections are unaffected. Your Pi can reach any server on the internet, and it can keep that connection open. That is the whole trick.

Turn the connection around

The agent on your Pi opens an SSH connection out to the relay and holds a reverse tunnel on it. The relay gives that tunnel a public port. You SSH to the relay on that port, and the connection is delivered to the Pi's own SSH server through the tunnel. Nothing inbound ever reaches your network. Your Pi checks your key or password, not the relay — we never hold your logins.

Install the agent on the Pi

Sign in, open Add device, and run the install command on the Pi. It needs Linux with systemd, Python 3.11 or newer, and ssh-keygen — Raspberry Pi OS has all three.

sh
curl -fsSL https://relayssh.com/install/YOUR-INSTALL-KEY/ | sudo sh

Add a tunnel to port 22

The Pi appears in the dashboard within a few seconds. On its page, add a tunnel to port 22. The relay assigns a public port between 20000 and 29999, and the agent opens the reverse tunnel to it.

SSH in

Use the assigned port and your usual username. The login is the Pi's own:

sh
ssh -p 20001 pi@relayssh.com

Nothing about your ISP, router, or WAN address is involved. Move the Pi to another CGNAT network and the same command still works.

What about IPv6?

Many ISPs that use CGNAT for IPv4 hand out public IPv6 addresses, and an IPv6 address is reachable from anywhere with IPv6 — no NAT at all. That is a real option if every network you will ever connect from also has IPv6. Many do not: hotel Wi-Fi, mobile data in some countries, and most corporate networks are still IPv4 only. A tunnel works from both. So does a mesh VPN, if every machine involved is yours to install on — RelaySSH vs Tailscale covers that trade.

Boundaries

The Pi needs outbound TCP to relayssh.com on ports 443 and 2002. CGNAT never blocks outbound traffic, but a strict firewall might block port 2002; if it does, the tunnel will not connect. A tunnel forwards one TCP port, so this is SSH access to the Pi, not a VPN into your network — for a NAS or camera next to the Pi, see reaching devices next to your Pi.