SSD Nodes Learn Hosting plans →
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-08-27

SSH su onion service Tor senza porte aperte

Configura sshd dietro un onion service Tor: VPS senza porte in ingresso, autorizzazione client v3 e ordine corretto per evitare di perdere l'accesso.

Cosa cambia con SSH tramite un onion service Tor

SSH tramite un onion service Tor consente di amministrare un VPS che non accetta connessioni in ingresso su alcuna porta. Il server avvia una connessione verso la rete Tor e la mantiene attiva. La sessione SSH torna indietro attraverso quella connessione, quindi non è necessario che ci sia un processo in ascolto sull'indirizzo IP pubblico.

L'effetto sui log è immediato. Un server con una porta SSH pubblica registra migliaia di tentativi di accesso con password non riusciti ogni giorno, provenienti dagli scanner. Sposta sshd dietro un onion service e blocca il traffico in ingresso sul firewall: /var/log/auth.log registrerà quindi soltanto le sessioni avviate da te.

Il costo è che tor si trova nel percorso di ogni sessione amministrativa. È un demone userspace che deve essere avviato e completare il bootstrap dopo ogni riavvio, prima che tu possa accedere. Pianificalo prima di chiudere la porta, perché in questo caso un errore significa perdere l'accesso a una macchina che non puoi raggiungere fisicamente.

Ottieni una via di accesso alternativa prima di modificare qualsiasi cosa

Non iniziare finché non hai un metodo di ripristino che non utilizzi SSH.

Apri subito la console del provider, cioè la console VNC o seriale disponibile nel pannello di controllo, e accedi tramite questa. Se non conosci la password di root, reimposta prima la password di root dal pannello e verifica che funzioni. Una console mai testata non è un metodo di ripristino.

L'ordine seguente è importante. Ogni passaggio viene verificato prima di eseguire quello successivo e la porta 22 rimane aperta finché il percorso onion non funziona.

  1. Installa tor e verifica che completi il bootstrap.
  2. Definisci il servizio onion e leggi l'indirizzo.
  3. Connettiti tramite onion mentre la porta 22 è ancora aperta.
  4. Aggiungi l'autorizzazione del client, quindi connettiti di nuovo.
  5. Associa sshd all'interfaccia loopback e chiudi la porta 22.
  6. Riavvia, quindi connettiti di nuovo tramite onion.

Mantieni aperta per tutto il processo la sessione SSH attuale. Una sessione già stabilita continua a funzionare anche dopo una modifica al firewall che impedirebbe nuove connessioni, quindi rappresenta la prima linea di ripristino.

Installare tor sul server

Ubuntu distribuisce tor nel proprio repository, ma quel pacchetto è spesso meno aggiornato. Il repository del Tor Project contiene la versione descritta nella relativa documentazione. Aggiungetelo eseguendo i comandi riportati nella guida al repository apt.

sudo apt update
sudo apt install -y apt-transport-https wget gpg
wget -qO- https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --dearmor | sudo tee /usr/share/keyrings/deb.torproject.org-keyring.gpg >/dev/null

Scrivete /etc/apt/sources.list.d/tor.sources. Suites usa il codename della release, che lsb_release -cs visualizza (noble su Ubuntu 24.04).

Types: deb deb-src
URIs: https://deb.torproject.org/torproject.org/
Suites: noble
Components: main
Signed-By: /usr/share/keyrings/deb.torproject.org-keyring.gpg
sudo apt update
sudo apt install -y tor deb.torproject.org-keyring
sudo journalctl -u tor@default -n 20 --no-pager

Il log dovrebbe terminare con Bootstrapped 100% (done). Se rimane bloccato prima di questo punto, tor non riesce a raggiungere la rete. Nella maggior parte dei casi, la causa è una regola del firewall in uscita oppure un orologio di sistema fortemente errato.

Il nome dell'unità può trarre in inganno. systemctl status tor restituisce Active: active (exited) anche quando tutto funziona correttamente, perché Debian e Ubuntu distribuiscono tor come un'unità master multi-instance, il cui unico compito è avviare l'istanza effettiva. Il demone viene eseguito come tor@default.service. Usate questo nome per status e journalctl. Le operazioni di avvio, arresto e ricaricamento di tor raggiungono comunque l'istanza, quindi sudo systemctl reload tor funziona come previsto.

Definire il servizio onion per la porta 22

Aggiungere due righe a /etc/tor/torrc.

HiddenServiceDir /var/lib/tor/ssh/
HiddenServicePort 22 127.0.0.1:22

La seconda riga indica a tor di accettare la porta virtuale 22 sull'indirizzo onion e di connettersi a 127.0.0.1:22 sul server. Tor raggiunge sshd tramite loopback; proprio per questo, in seguito, sshd può smettere di essere in ascolto sull'indirizzo pubblico. Puntare invece quella seconda riga a un web server su 127.0.0.1:80 e le stesse due direttive pubblicano un sito su un indirizzo onion, una seconda utile funzione da attivare dopo l'installazione di tor.

sudo systemctl reload tor
sudo cat /var/lib/tor/ssh/hostname

Il comando stampa 56 caratteri base32 seguiti da .onion. Questi caratteri rappresentano la chiave pubblica del servizio in forma codificata. Non sono coinvolti né un'autorità di certificazione né una registrazione del nome.

Lasciare che sia tor a creare /var/lib/tor/ssh/. Se la directory viene creata manualmente con il proprietario errato o con permessi più permissivi di 0700, tor rifiuta di utilizzarla e il journal segnala che la directory dispone di permessi eccessivi. I file al suo interno costituiscono l'identità del servizio: hs_ed25519_secret_key è l'indirizzo. Eseguire il backup di questa directory con modalità 600 e conservare la copia fuori dal server, perché perderla comporta la generazione di un nuovo indirizzo e la modifica della configurazione su ogni client.

Connessione dalla workstation

La workstation deve avere un client Tor, che non richiede alcuna configurazione. Su Debian o Ubuntu il pacchetto è sudo apt install -y tor netcat-openbsd. Tor resta quindi in ascolto su 127.0.0.1:9050 come proxy SOCKS5. SOCKS è un protocollo proxy generico. La versione 5 può trasportare un hostname invece di un indirizzo IP. È questo l'aspetto importante in questo caso.

OpenSSH non include un client SOCKS. Perciò la connessione viene gestita da un programma di supporto. Aggiungere quanto segue a ~/.ssh/config.

Host myvps
  HostName xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.onion
  User admin
  ProxyCommand /usr/bin/nc -X 5 -x 127.0.0.1:9050 %h %p
  ServerAliveInterval 30

-X 5 seleziona SOCKS5 e -x 127.0.0.1:9050 indica il processo Tor locale. %h passa il nome onion a Tor come nome, in modo che Tor lo risolva all'interno della rete. Deve essere la versione OpenBSD di netcat. GNU netcat non dispone dell'opzione -X e termina con nc: invalid option -- 'X'.

ssh myvps

La prima connessione è lenta, perché Tor costruisce un circuito prima di procedere. Accettare l'impronta della chiave host come si farebbe in qualsiasi altro caso. Da questo momento si applica senza modifiche la normale gestione delle chiavi SSH. È cambiato il trasporto. L'autenticazione no.

Per un utilizzo occasionale si può omettere la voce di configurazione: torsocks ssh admin@xxxxx.onion svolge la stessa funzione.

Aggiungere l'autorizzazione del client v3

Nello stato attuale, chiunque venga a conoscenza dell'indirizzo può raggiungere il banner SSH e iniziare a tentare le credenziali. Gli indirizzi onion non possono essere enumerati tramite il sistema di directory, quindi l'indirizzo si comporta come un secret. Tuttavia, può fuoriuscire in modi ordinari: dalla cronologia della shell o da file di configurazione sottoposti a commit in un repository git. L'autorizzazione del client elimina questa esposizione. Il servizio pubblica il proprio descriptor cifrato con una chiave client, quindi chi possiede l'indirizzo ma non la chiave non può nemmeno individuare il servizio.

Generare una coppia di chiavi x25519 sul client. Questa è la pipeline della guida all'autorizzazione del client del Tor Project, con una modifica.

openssl genpkey -algorithm x25519 -out /tmp/k1.prv.pem
grep -v " PRIVATE KEY" /tmp/k1.prv.pem | base64 -d | tail --bytes=32 | base32 | sed 's/=//g' > /tmp/k1.prv.key
openssl pkey -in /tmp/k1.prv.pem -pubout | grep -v " PUBLIC KEY" | base64 -d | tail --bytes=32 | base32 | sed 's/=//g' > /tmp/k1.pub.key

La versione pubblicata di queste righe usa base64pem -d, che non è incluso in un'installazione standard di Ubuntu. Il comando si interrompe quindi con base64pem: command not found. GNU base64 -d decodifica lo stesso corpo PEM, quindi usare quello.

Sul server, installare la chiave pubblica.

sudo install -d -m 700 -o debian-tor -g debian-tor /var/lib/tor/ssh/authorized_clients
echo "descriptor:x25519:PASTE_PUBLIC_KEY_HERE" | sudo tee /var/lib/tor/ssh/authorized_clients/laptop.auth >/dev/null
sudo chown debian-tor:debian-tor /var/lib/tor/ssh/authorized_clients/laptop.auth
sudo systemctl reload tor

Vengono letti soltanto i file che terminano con .auth. Salvarla come laptop.auth.txt: tor ignora il file senza stampare errori e il servizio rimane silenziosamente accessibile a chiunque disponga dell'indirizzo.

Sul client, installare la chiave privata. In Ubuntu, il demone tor viene eseguito come utente debian-tor e non può leggere i file nella directory home dell'utente, quindi conservare la directory in un percorso accessibile a quell'utente.

sudo install -d -m 700 -o debian-tor -g debian-tor /var/lib/tor/onion_auth
echo "ADDRESS_WITHOUT_DOT_ONION:descriptor:x25519:PASTE_PRIVATE_KEY_HERE" | sudo tee /var/lib/tor/onion_auth/myvps.auth_private >/dev/null
sudo chown debian-tor:debian-tor /var/lib/tor/onion_auth/myvps.auth_private
sudo chmod 600 /var/lib/tor/onion_auth/myvps.auth_private

Aggiungere ClientOnionAuthDir /var/lib/tor/onion_auth a /etc/tor/torrc del client e ricaricare tor. Se invece si esegue tor con il proprio utente, ad esempio con la build Homebrew su macOS, impostare ClientOnionAuthDir su ~/.tor/onion_auth con modalità 0700.

L'indirizzo contenuto in quel file è composto dai 56 caratteri senza il suffisso .onion. Eliminare /tmp/k1.prv.pem e /tmp/k1.prv.key al termine.

Ora verificare entrambe le direzioni. ssh myvps dovrebbe continuare a connettersi. Da una macchina che non dispone della chiave, lo stesso indirizzo dovrebbe restituire un errore. Questo dimostra che l'autorizzazione è attiva.

Chiudere la porta 22 in questo ordine

Impostare prima una rete di sicurezza. Questo comando annulla entrambe le modifiche riportate sotto dopo quindici minuti, se si perde l’accesso al server.

sudo systemd-run --on-active=15m --unit=ssh-rescue \
  /bin/sh -c 'ufw allow 22/tcp; rm -f /etc/systemd/system/ssh.socket.d/override.conf; systemctl daemon-reload; systemctl restart ssh.socket'

Annullarlo con sudo systemctl stop ssh-rescue.timer dopo aver verificato che la route onion funzioni ancora.

Quindi impedire a sshd di restare in ascolto sull’indirizzo pubblico. Ubuntu 24.04 attiva SSH tramite una socket unit, quindi ListenAddress in sshd_config viene ignorato: ssh.socket gestisce la socket in ascolto, non sshd. Verificare quale dei due casi si applica.

systemctl is-enabled ssh.socket

Se il comando restituisce enabled, eseguire sudo systemctl edit ssh.socket e aggiungere quanto segue.

[Socket]
ListenStream=
ListenStream=127.0.0.1:22

Il valore vuoto di ListenStream= cancella il valore ereditato dalla unit fornita dal pacchetto. Se si omette quella riga, si aggiunge un secondo listener mantenendo attivo quello pubblico. È il modo più comune in cui questo passaggio non riesce senza segnalarlo.

sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
ss -tlnp | grep ':22'

ss dovrebbe mostrare 127.0.0.1:22 e nessun risultato su 0.0.0.0:22. Se ssh.socket era disabilitato, inserire ListenAddress 127.0.0.1 in /etc/ssh/sshd_config.d/10-onion.conf, eseguire sudo systemctl restart ssh, quindi verificare con la stessa riga ss. In entrambi i casi, quell’output costituisce la verifica.

Poi configurare il firewall, con la normale gestione delle regole ufw su un VPS. Eseguire prima sudo ufw status numbered e rimuovere la regola SSH indicata.

sudo ufw status numbered
sudo ufw delete allow OpenSSH
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw status verbose

Lasciare consentito il traffico in uscita. Tor si connette ai relay sulle porte, ad esempio, 443 e 9001. Una policy predefinita deny per il traffico in uscita impedisce l’avvio della connessione Tor e rimuove nello stesso momento l’unico accesso residuo al server. La maggior parte dei provider gestisce anche un firewall di rete separato nel pannello di controllo. Chiudere la porta 22 anche in quel firewall. In caso contrario, la porta resterà raggiungibile indipendentemente da quanto riportato da ufw.

Se Docker è in esecuzione su questo server, controllare le porte pubblicate prima di considerare conclusa l’operazione. Docker scrive le proprie regole nelle stesse tabelle e pubblica direttamente le porte dei container oltre ufw, quindi una policy deny di ufw non rappresenta l’intero perimetro di esposizione.

Riavvia prima di considerarlo affidabile

systemctl is-enabled tor@default
sudo reboot

Se il primo comando non indica il servizio come abilitato, esegui sudo systemctl enable tor@default prima del riavvio. Attendi due minuti, quindi esegui ssh myvps. Tor deve completare il bootstrap dopo l'avvio, quindi l'indirizzo onion inizia a rispondere qualche tempo dopo che la macchina è diventata operativa.

Se il servizio non torna mai operativo, apri la console e leggi sudo journalctl -u tor@default -b. Qui vengono visualizzati gli errori di sintassi di torrc o i problemi relativi ai permessi della directory. Puoi anche verificare una modifica di torrc prima di applicarla.

sudo -u debian-tor tor --verify-config

Quanto costa rispetto a un tunnel WireGuard

Rispetto a una VPN WireGuard sul proprio VPS, un onion service è più lento e meno prevedibile. Valutate con attenzione questo compromesso prima di adottarlo.

Latenza. Il circuito del client usa tre relay e il lato del servizio ne aggiunge altri tre, quindi i caratteri digitati attraversano circa sei macchine scelte casualmente in tutto il mondo. La digitazione interattiva presenta un ritardo evidente e la copia dei file è lenta. WireGuard aggiunge un solo hop. Misurate il vostro caso con time ssh myvps 'echo ok', perché il valore dipende dal circuito che tor ha costruito in quel momento e cambia quando tor ne costruisce un altro.

Un daemon userspace nel percorso critico. WireGuard opera nel kernel e viene avviato insieme alla rete. Tor è un processo che deve avviarsi, completare il bootstrap e raggiungere un relay guard prima che tutto funzioni. Quando si verifica un errore, dovete usare la console del provider.

Precisione dell'orologio. I descrittori degli onion service vengono pubblicati in base a intervalli temporali, quindi un orologio fortemente sfasato impedisce la risoluzione dell'indirizzo senza produrre messaggi chiari. timedatectl dovrebbe restituire System clock synchronized: yes.

In cambio ottenete un'esposizione che non dipende più dal corretto funzionamento di una regola firewall. Non c'è alcuna porta da sottoporre a scansione né alcun banner da acquisire. Inoltre, l'indirizzo è una chiave pubblica, quindi l'endpoint dimostra la propria identità prima ancora che SSH venga avviato.

Nella pratica, la soluzione migliore è spesso usare entrambi. Usate WireGuard come percorso quotidiano e mantenete l'onion service come percorso funzionante anche quando la configurazione WireGuard è errata. In questo modo resta aperta una sola porta UDP, invece di una porta SSH pubblica. Nulla di tutto questo sostituisce la messa in sicurezza di sshd stesso: l'autenticazione basata soltanto su chiavi e un accesso non-root restano importanti, perché un onion service protegge il percorso di rete e nient'altro oltre a quello.

Modalità di errore e messaggi visualizzati

Tor non supera Bootstrapped 0%. Il traffico in uscita è bloccato oppure l'orologio del sistema è molto fuori sincronizzazione. Controlla la policy in uscita con sudo ufw status verbose, quindi esegui timedatectl.

systemctl status tor restituisce active (exited). Questo comportamento è normale su Debian e Ubuntu. Consulta invece tor@default.

Il descriptor non è disponibile. Tor restituisce l'errore SOCKS esteso F0, "Onion Service Descriptor Can Not be Found". Il descriptor potrebbe non essere ancora stato pubblicato, perché dopo un reload è necessario attendere brevemente, oppure tor sul server potrebbe non essere in esecuzione.

F4, "Onion Service Missing Client Authorization". Il client non dispone di un .auth_private corrispondente che tor possa utilizzare. Verifica che ClientOnionAuthDir sia presente in torrc, che la directory abbia modalità 0700, che il nome del file termini con .auth_private e che debian-tor possa leggerlo.

F5, "Onion Service Wrong Client Authorization". La chiave privata non corrisponde al file .auth sul server. Questo errore è causato da un = finale o da un carattere di nuova riga estraneo all'interno della stringa base32.

nc: invalid option -- 'X'. È installato GNU netcat invece della versione OpenBSD. Esegui sudo apt install -y netcat-openbsd.

Could not resolve hostname. ssh ha tentato una normale risoluzione DNS, che non restituisce risultati per .onion; di conseguenza ProxyCommand non è mai stato eseguito. Il pattern Host in ~/.ssh/config non corrisponde al nome digitato.

Permission denied (publickey). Il tunnel ha funzionato e tor ha completato il proprio lavoro. Gestisci il problema come un normale errore publickey con permission denied e non considerare tor nella diagnosi.

FAQ

Un onion service significa davvero che non ci sono porte aperte sul mio VPS?

Sì, quando sshd è in ascolto su 127.0.0.1 e il firewall blocca il traffico in ingresso. Tor stabilisce una connessione TCP in uscita verso un relay e la sessione torna indietro attraverso quella connessione. Sul server, quindi, nessun servizio accetta connessioni sull'indirizzo pubblico. Verificalo con ss -tlnp sul server e con una scansione delle porte da un altro sistema. Non dimenticare il firewall di rete del provider nel pannello di controllo. È un controllo separato da ufw e deve essere chiuso a sua volta.

L'indirizzo .onion offre da solo una sicurezza sufficiente per SSH?

No. L'indirizzo contiene 56 caratteri e non può essere indovinato o enumerato tramite il sistema di directory. Si comporta quindi come un secret, ma può essere esposto nella cronologia della shell e nei file di configurazione. Aggiungi l'autorizzazione client v3. In questo modo, il service descriptor viene cifrato con la chiave del client. Chi possiede soltanto l'indirizzo riceve l'errore esteso F4 e non raggiunge mai sshd.

Cosa succede se Tor non si avvia dopo un riavvio?

Perdi completamente l'accesso SSH, perché a quel punto l'indirizzo onion è l'unico modo per accedere al server. Per questo devi testare la console del provider prima di chiudere la porta 22. Dopo l'avvio, Tor ha bisogno di tempo per completare il bootstrap, quindi l'indirizzo risponde più tardi rispetto al sistema ai ping. Se non risponde mai, accedi dalla console e leggi sudo journalctl -u tor@default -b. Qui vengono riportati gli errori di sintassi di torrc o i problemi di permessi su /var/lib/tor/ssh.

SSH tramite Tor è più lento di WireGuard?

Sì, con una differenza significativa. Una connessione a un onion service attraversa circa sei relay scelti casualmente, mentre WireGuard utilizza un singolo hop cifrato diretto verso il server. La digitazione presenta ritardo e i trasferimenti sono lenti. Una configurazione comune prevede WireGuard per le attività quotidiane e l'onion service come percorso di emergenza, disponibile anche quando una configurazione VPN non funzionante impedisce l'accesso.