SSH Over an Onion Service
Created September 12, 2026 • Last updated September 12, 2026 • 3 min read • 260 views
Running SSH over an onion service takes your management port off the public internet entirely. Nothing listens on a routable address, so a scan finds no SSH to attack. This pairs with the anonymous build from the hardened onion service guide. You reach the box only through Tor.
Reach SSH over an onion service
The order matters. Bind sshd to loopback, add a HiddenServicePort for port 22, and confirm you can log in over Tor. Only then close the public port. Follow it in that sequence, or a mistake in the Tor config locks you out of a box with no public SSH.
Bind sshd to loopback
Tell sshd to listen only on loopback. Recent Debian ships an Include line for /etc/ssh/sshd_config.d/ in the main config, so a drop-in file is enough. Create it, then restart the service.
ListenAddress 127.0.0.1
ListenAddress ::1
tcp LISTEN 0 128 127.0.0.1:22 0.0.0.0:* users:(("sshd",pid=744,fd=3))
tcp LISTEN 0 128 [::1]:22 [::]:* users:(("sshd",pid=744,fd=4))
Add the SSH onion
Give SSH its own service so it has a separate address from the website. Append the block to /etc/tor/torrc and restart Tor. Read the new hostname from the service directory.
HiddenServiceDir /var/lib/tor/ssh/
HiddenServicePort 22 127.0.0.1:22
3cb6rnxga23uh2m4qkolmk4wpgw45qmddn4ufhl74jdaimn5mqs7eyid.onion
Restrict this onion to your own key with client authorization, so the SSH service is invisible to anyone else. The setup is the same as the admin onion in running multiple onion services on one host.
Connect from the client
The simplest way wraps ssh with torsocks, which sends the connection through the local Tor SOCKS port. Replace $USER with your login and $ONION_ADDRESS with the SSH onion. Keep sshd on key authentication only, since the onion layer does not replace a login credential.
For a permanent setup, add a host entry to ~/.ssh/config with a ProxyCommand that speaks SOCKS5 to Tor. ssh does not expand variables in this file, so replace $ONION_ADDRESS and $USER with the real values. The default netcat on Debian is the OpenBSD build, which supports the flags below. If you prefer ncat, install it with apt install ncat, then use ncat --proxy 127.0.0.1:9050 --proxy-type socks5 %h %p.
Host myonion
HostName $ONION_ADDRESS
User $USER
ProxyCommand nc -X 5 -x 127.0.0.1:9050 %h %p
Close the public port last
Only remove the public SSH rule after the onion login works. Capture the host key fingerprint on the server first, so you can compare it against the prompt on the client and trust the first onion connection.
Warning
Keep an out-of-band way back in before you drop the public SSH rule. If Tor fails to start or the key is wrong, an onion-only sshd locks you out. A serial or provider console covers that case.
256 SHA256:uAlsALpkNzr/SacdJDc7Siewkrf7SDzkdZr42rtF/K8 root@host (ED25519)
Now remove the tcp dport 22 accept line from the input chain in the firewall and reapply the ruleset. A scan of the public IP then shows port 22 as filtered, and the box exposes nothing on a public address.
This closes the last public port from the hardened onion service build. Give the SSH onion a readable prefix with mkp224o if you like.
References
-
Tor onion service setupLINK: Tor onion service setup, community.torproject.org/onion-services/setup (opens in new tab)
Adding a HiddenServicePort for a service such as sshd.
-
Wrapper that routes a program through the Tor SOCKS port.