Two independent benefits: your server never sees the IP address you administer it from, and SSH can be firewalled off the public internet completely, which removes it as an attack surface.
On the server
apt -y install tor
cat >> /etc/tor/torrc <<'EOF'
HiddenServiceDir /var/lib/tor/ssh/
HiddenServicePort 22 127.0.0.1:22
HiddenServiceVersion 3
EOF
systemctl restart tor
cat /var/lib/tor/ssh/hostname
That prints your .onion address. Save it somewhere durable โ losing it while public SSH is firewalled off means recovering through the KVM console.
On your workstation
# ~/.ssh/config
Host myserver
HostName xxxxxxxx.onion
User deploy
ProxyCommand /usr/bin/nc -X 5 -x 127.0.0.1:9050 %h %p
ssh myserver
Expect roughly 200โ500 ms of added latency. Fine for administration; unpleasant for anything interactive at scale.
Close public SSH
Only after you have confirmed the onion route works, from a fresh terminal:
ufw delete allow 22/tcp
# Tor connects to 127.0.0.1:22 locally, so sshd stays reachable
ss -tlnp | grep :22
SSH is now reachable only through the hidden service. Port scans of your IPv4 show nothing on 22.
Client authentication (optional)
By default anyone who learns your onion address can reach the SSH banner. Version 3 onion services support client authorisation, so only holders of a specific key can even complete the handshake:
# On the client
openssl genpkey -algorithm x25519 -out /tmp/k.prv.pem
# Derive the base32 public key and place it in
# /var/lib/tor/ssh/authorized_clients/alice.auth on the server
With this enabled, the service is invisible to anyone without the key even if the address leaks.