SSH without opening port 22: comparison table and real commands
You can reach a server by SSH without opening port 22 to the internet by putting both ends on a WireGuard mesh. The server listens only on its private 100.64.x.x address, and nothing is forwarded on the router. Scanners on the public internet then find no SSH service to probe, guess passwords against or exploit.
What an open port 22 exposes on a server reachable from the internet
A port 22 forwarded on the router or open on a cloud firewall answers anyone who sends it a packet. The SSH daemon has to accept the TCP connection, negotiate keys and process the login attempt before it knows who is on the other side. That puts three things in front of the whole internet: the daemon's own code, any account that still accepts passwords, and the fact that a server exists at that address. Moving SSH to another port number hides it from casual scans but changes none of the three.
How prialo carries SSH over WireGuard with no inbound ports
In prialo, every device holds its own WireGuard key pair and gets one fixed address inside 100.64.0.0/10, the shared address space of RFC 6598. As a result, it never collides with a 192.168.x.x or 10.x.x.x LAN. The SSH client connects to that address, and the packets travel inside the tunnel. There is no username or password on the data path, only keys.
Nothing is opened on the router. The two ends negotiate a direct path with STUN (UDP 3478 on the control plane) and hole punching. When that fails because of carrier CGNAT, symmetric NAT or another VPN in front, traffic goes through a relay on TCP 4430 that forwards packets it cannot decrypt. In both cases, the server only makes outbound connections.
Once the server is on the mesh, sshd can listen only on its 100.64 address, and the port 22 forward can be removed. SSH keys and the usual sshd hardening stay in place. The mesh adds a layer in front of the server but does not replace authentication on it.
Port 22 open versus SSH over prialo: what is exposed in each case
| Exposed element | Port 22 open to the internet | SSH over prialo with port 22 closed |
|---|---|---|
| SSH daemon | Reachable from any address on the internet | Reachable only from devices enrolled in the mesh |
| Password guessing | Possible against any account that accepts passwords | No path: the data plane uses WireGuard keys only |
| Router configuration | Port forward or firewall rule required | No inbound ports opened |
| Server behind CGNAT | Unreachable without a public IP | Direct path or relay on TCP 4430 |
| Who can connect | Anyone who passes the SSH login | Approved devices with valid keys, recorded in the audit log |
Joining a Linux server to prialo step by step
- Create an enrolment key: in the administration, generate a single-use key that expires. Keys can also be reusable, and all keys are revocable.
- Install the node as root: run the command below with the server address, relay and SPKI fingerprint of your control plane.
- Check the control channel: prialo status must show 'Control: tls, pinned' and an IP inside 100.64.0.0/10. prialo ip prints that address.
- Test from your laptop: prialo ping <host-or-ip> confirms the path. Then ssh to the 100.64 address.
- Close port 22 on the internet side: remove the router forward or cloud firewall rule, and bind sshd to the mesh address.
sudo PRIALO_AUTH_KEY='<enrolment key>' prialo install --server=control.example.com:50051 --relay=control.example.com:4430 --tls-pin=sha256:<fingerprint>
A node refuses a control server that does not present the pinned key, so no certificate authority is part of the trust model. Device approval and an audit log of every administrative event record who added the server and when. For several customer sites, the MSP workflow is covered in SSH and RDP to customer servers.
What remains exposed when the prialo control plane is self-hosted
Closing port 22 on every server moves the public surface to one machine. The self-hosted package runs three containers with Docker Compose: the coordination server, the relay and PostgreSQL. It publishes gRPC on TCP 50051, STUN on UDP 3478 and the relay on TCP 4430. The admin API on port 8080 is never published to the internet, and the dashboard is reached through an SSH tunnel. That machine therefore needs well-protected SSH access of its own. The keys and the database stay on the customer's server, and Sinergia does not access that instance. Ports and backups are detailed in the self-hosted control plane guide.
Relay traffic and quota for SSH sessions over prialo
Relayed SSH uses well under 1 MB per hour. An interactive session therefore barely registers against the 10 GB of relayed traffic a month in the Free plan or the 100 GB per person in Teams (5 EUR per person per month, excluding VAT). Remote desktop is different, at 0.5 to 1 GB per hour. Forwarding one frame takes about 23 ns and does not depend on how many clients are connected. On a self-hosted relay, PRIALO_MESH_QUOTA_BYTES caps relayed egress per mesh per month. Past the cap, frames are dropped and counted, without disconnecting anyone.
What prialo cannot do yet for SSH from phones and Windows
On 17 October 2026, the Mac and iPhone apps are in Apple's review queue and cannot be downloaded yet. Android is in preparation, and the Windows client is an early build without installer or signature. The command-line client for Linux and macOS and the self-hosted package work today. An SSH client such as Termi1 for iPhone and iPad can reach a 100.64 address only once the iPhone app is available. Phones and Windows do not accept subnet routes yet, and only Linux can act as a router.
Frequently asked questions
Is SSH over prialo safe with port 22 closed on the router?
SSH over prialo with port 22 closed removes the server from public scans and password guessing from the internet. Only enrolled devices with WireGuard keys reach its 100.64 address. SSH authentication still applies on the server, so key-only logins and normal sshd hardening remain worth keeping.
Does SSH through prialo work behind carrier CGNAT?
SSH through prialo works behind carrier CGNAT. Nodes first try a direct path with STUN and hole punching. When CGNAT or symmetric NAT blocks that path, traffic goes through the relay on TCP 4430, which forwards packets it cannot decrypt. The server needs no public IP or inbound port.
How much relayed traffic does an SSH session use on prialo?
A relayed SSH session on prialo uses well under 1 MB per hour. The Free plan includes 10 GB of relayed traffic a month for up to 10 devices, and Teams includes 100 GB per person a month. SSH alone therefore rarely comes close to either limit.
Do I need to open any port to self-host the prialo control plane?
Self-hosting the prialo control plane requires publishing TCP 50051 for gRPC, UDP 3478 for STUN and TCP 4430 for the relay on that one server. The admin API on port 8080 stays unpublished, and the dashboard is reached through an SSH tunnel. The nodes themselves open no inbound ports.
Would you rather run your own server? Guide to the self-hosted prialo package