How to Connect to Your VPS Over Tor
Anonymity ยท 8 min read
Two different problems, both called 'SSH over Tor'
People searching for tor vps access are usually trying to solve one of two distinct problems, and the setup differs depending on which one applies. The first is client-side: you want to hide your own IP address from the server, from anyone watching your local network, and from anyone who later subpoenas the VPS provider's connection logs. The second is server-side: you want the VPS itself to have no SSH port reachable from the public internet at all, so it cannot be found by a port scanner, targeted by a credential-stuffing bot, or geolocated by its listening service.
These are not mutually exclusive. A lot of the confusion in forum threads about ssh over tor comes from people mixing up 'I want to hide who is connecting' with 'I want to hide what is being connected to.' This guide covers both, starting with the simpler client-side setup, then the onion-service approach for the server, then how to harden the result and what performance to actually expect.
- Client-side anonymity: your SSH client routes through Tor so the server (and anyone logging its inbound connections) sees a Tor exit or relay, not your real IP
- Server-side anonymity: sshd is only reachable through a Tor onion address, so there is no public IP:port for SSH at all
Method 1: route your SSH client through Tor's SOCKS proxy
A running Tor client (the Tor daemon, not necessarily Tor Browser) exposes a local SOCKS5 proxy, by default at 127.0.0.1:9050. Any SOCKS-aware application can be pointed at it, and SSH itself doesn't speak SOCKS natively, so you need a small bridge. The two common approaches are torsocks, which wraps a command and forces its TCP connections through the proxy, and a ProxyCommand entry in your SSH config that pipes the connection through a SOCKS-capable netcat.
The quickest test is simply: install tor, confirm it's running, then run torsocks ssh user@your-vps-ip. If that connects, your SSH session is now routed through a three-hop Tor circuit. For something you'll use daily, add a Host block to ~/.ssh/config instead of typing torsocks every time, using a ProxyCommand line such as nc -X 5 -x 127.0.0.1:9050 %h %p (with OpenBSD netcat) or connect -S 127.0.0.1:9050 %h %p (with the connect-proxy tool). That way plain ssh myhost works and always goes through Tor without you having to remember the wrapper.
- Verify Tor is actually running and listening on 9050 before troubleshooting SSH itself
- torsocks ssh user@host is the fastest way to test; a ProxyCommand in ~/.ssh/config is the durable way to use it day to day
- This method hides your IP from the VPS and from anyone reading its auth logs, but the SSH port itself is still open to the public internet
Method 2: publish SSH as a Tor onion service on the VPS
If the goal is to keep the VPS's own IP address out of the picture entirely for admin access, the server needs to run Tor and expose sshd only as a hidden service. Install tor on the VPS, then add two lines to torrc: HiddenServiceDir pointing at a directory Tor can write to, and HiddenServicePort 22 127.0.0.1:22, which tells Tor to forward connections arriving at the onion address's port 22 to the locally-listening sshd. Restart Tor, and it generates a long random .onion hostname in that directory the first time it starts.
Crucially, this step only removes exposure if sshd is also told to bind to 127.0.0.1 rather than the VPS's public interface (ListenAddress 127.0.0.1 in sshd_config, then restart sshd). Skipping that step leaves SSH reachable both through the onion address and directly on the public IP, which defeats the point. Once that's done, connect from the client side with torsocks ssh [email protected] โ no public IPv4 or IPv6 address for SSH ever appears in a port scan of the VPS.
- Add HiddenServiceDir and HiddenServicePort 22 127.0.0.1:22 to torrc, then restart Tor
- Bind sshd itself to 127.0.0.1 only โ an onion service in front of a still-public port hides nothing
- Read the generated hostname file inside the HiddenServiceDir to get the .onion address to connect to
- Connect with torsocks ssh [email protected]; a bare IP will no longer work for SSH at all
Locking down authentication once SSH only answers on .onion
Hiding the port doesn't replace hardening the login. Use ed25519 keypairs, disable password authentication entirely (PasswordAuthentication no), and disable root login over SSH (PermitRootLogin no). If the key you use to reach this VPS is the same one you use for your everyday accounts, the anonymity gained by the onion service is undermined the moment that key's fingerprint shows up in a breach dump or a Shodan/Censys scan tied to your name elsewhere โ generate a dedicated key for anonymous infrastructure.
One thing that quietly stops working in this setup: IP-based tools like fail2ban. Because connections arrive at sshd via the local Tor process, the source address sshd logs is 127.0.0.1 for every single login attempt, successful or not โ there's no attacker IP to ban. That's not a gap you need to fill with a workaround; key-only authentication with no password fallback already removes the brute-force risk fail2ban exists to mitigate. Just don't expect its logs to be meaningful in this configuration.
- Key-only auth, ed25519, no password fallback
- A dedicated keypair per anonymous server, never reused from a personal machine
- PermitRootLogin no, and a non-root account with sudo for actual work
- Don't rely on fail2ban or IP allowlisting once traffic arrives via Tor โ the source IP in logs is always loopback
What performance actually looks like
A standard Tor circuit is three relays, and an onion-service connection stacks two three-hop circuits end to end (one from the client into the Tor network, one from the Tor network to the hidden service), so round-trip latency commonly lands somewhere between a few hundred milliseconds and a couple of seconds, with occasional spikes when a circuit rebuilds. Interactive work โ editing config files, checking logs, restarting a service โ is entirely usable at that latency. Set ServerAliveInterval in your SSH config so idle sessions don't get dropped by the extra hop, and expect the occasional stall while Tor picks a new circuit.
What doesn't work well is throughput. scp, rsync, or anything moving gigabytes will crawl compared to a direct connection, because Tor circuits are optimized for low-latency interactivity across many short-lived streams, not sustained bandwidth. For actual data transfer โ backups, large uploads โ use a direct encrypted channel (plain SSH/rsync over the public IP, or a WireGuard tunnel) and reserve the Tor path specifically for administrative shell access where hiding the connection matters more than speed.
Mistakes that quietly break the anonymity you were trying to get
Most failures here aren't exotic โ they're small configuration gaps that leave a side door open. Watch for these before you trust the setup:
None of these require advanced tooling to avoid; they just require checking the actual listening ports and DNS behavior once, rather than assuming the Tor configuration alone did the job.
- sshd still bound to the public interface alongside the onion service, so the 'hidden' port is also findable by a plain port scan
- Resolving hostnames outside of Tor (a stray DNS lookup, or an application that ignores the SOCKS proxy for DNS) leaks which host you're about to connect to before the Tor connection even starts
- A ProxyCommand that silently falls back to a direct connection if Tor isn't running โ configure it to fail closed, not open, so a dead Tor daemon means no connection rather than an accidental clearnet one
- Reusing an SSH key, terminal prompt, or shell history that ties this session back to a non-anonymous identity elsewhere
| Method | What it hides | Typical added latency | Setup effort |
|---|---|---|---|
| Direct SSH over the clearnet | Nothing beyond SSH's own encryption | None | None |
| Client routed through Tor's SOCKS proxy | Your IP address, from the server and its logs | Moderate โ roughly one Tor circuit, ~300ms-1s | Low โ torsocks or a ProxyCommand line |
| SSH published as a Tor onion service | The VPS's public IP; no open SSH port on the internet | Moderate to high โ server-side circuit added | Medium โ torrc and sshd_config changes |
| Both combined: client via Tor, server as onion service | Both ends of the connection stay off the clearnet entirely | Highest โ two independent 3-hop circuits | Medium |
FAQ
Does SSH over Tor weaken SSH's encryption?+
Is SSH over Tor too slow for real administration work?+
Can I still use fail2ban if SSH is only reachable through an onion service?+
Do I need a VPN as well as Tor for VPS access?+
Do both ends need to run Tor, or just my laptop?+
Ready to go offshore?
No KYC, no email โ just an anonymous key and crypto. Deploy in ~55 seconds.
Configure your VPS โ