SSD Nodes Learn 🎉 VPS da $5.50/mese
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-08-13

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 dei passaggi per evitare il lockout.

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 nessuna porta. Il server avvia la connessione verso la rete Tor e la mantiene attiva. La sessione SSH viaggia attraverso questa connessione, quindi nessun servizio deve restare in ascolto sull'indirizzo IP pubblico.

L'effetto sui log è immediato. Un server con una porta SSH pubblica registra migliaia di tentativi di autenticazione con password non riusciti ogni giorno, generati 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 limite è che tor si trova nel percorso di ogni sessione di amministrazione. È un demone in userspace che deve avviarsi e completare il bootstrap dopo ogni riavvio, prima che tu possa effettuare l'accesso. Pianifica questa condizione prima di chiudere la porta, perché in caso di errore potresti perdere l'accesso a una macchina che non puoi raggiungere fisicamente.

Prepara un metodo di accesso alternativo prima di modificare qualsiasi cosa

Non iniziare finché non disponi di un percorso 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 quella. Se non conosci la password di root, reimposta prima la password di root dal pannello e verifica che funzioni. Una console che non hai mai testato non costituisce un percorso 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 di loopback e chiudi la porta 22.
  6. Riavvia il sistema, quindi connettiti di nuovo tramite onion.

Mantieni aperta l'attuale sessione SSH per tutta la procedura. Una sessione già stabilita rimane attiva anche dopo una modifica del firewall che impedirebbe nuove connessioni, quindi costituisce la prima possibilità di ripristino.

Installare tor sul server

Ubuntu distribuisce tor nel proprio repository, ma questa build è spesso obsoleta. Il repository di Tor Project contiene la versione descritta nella relativa documentazione. Aggiungilo usando i comandi della 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

Scrivi /etc/apt/sources.list.d/tor.sources. Suites restituisce il codename della release, che lsb_release -cs stampa (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 resta fermo prima di questo punto, tor non riesce a raggiungere la rete. Nella quasi totalità dei casi, la causa è una regola del firewall per il traffico in uscita oppure un orologio di sistema fortemente errato.

Il nome dell'unità è ingannevole. systemctl status tor restituisce Active: active (exited) anche quando tutto funziona correttamente, perché Debian e Ubuntu distribuiscono tor come un'unità master multi-istanza il cui unico compito è attivare l'istanza reale. Il demone viene eseguito come tor@default.service. Usa 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

Aggiungi 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. Per questo motivo, in seguito sshd può smettere di restare in ascolto sull'indirizzo pubblico.

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

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

Lascia che sia tor a creare /var/lib/tor/ssh/. Se lo crei manualmente con il proprietario errato o con permessi più permissivi di 0700, tor rifiuta di usarlo e il journal segnala che la directory ha permessi troppo permissivi. I file al suo interno identificano il servizio: hs_ed25519_secret_key è l'indirizzo. Esegui il backup di quella directory con permessi 600 e conserva la copia fuori dal server, perché perderla comporta un nuovo indirizzo e una modifica della configurazione su ogni client.

Connettersi dalla workstation

La workstation richiede un client Tor, che non necessita di 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 nome host invece di un indirizzo IP. È questo l'aspetto rilevante in questo caso.

OpenSSH non include un client SOCKS. Per stabilire la connessione serve quindi 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 inoltra a Tor il nome onion come nome, così Tor lo risolve all'interno della rete. È necessario usare OpenBSD netcat. GNU netcat non dispone dell'opzione -X e termina con nc: invalid option -- 'X'.

ssh myvps

La prima connessione è lenta perché Tor crea un circuito prima di procedere. Accettare l'impronta della chiave host come per qualsiasi altra connessione. Da questo momento si applica senza modifiche la consueta gestione delle chiavi SSH. Cambia il trasporto. L'autenticazione non cambia.

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

Così com'è, chiunque venga a conoscenza dell'indirizzo può raggiungere il banner SSH e iniziare a tentare combinazioni. Gli indirizzi Onion non possono essere enumerati dal sistema di directory, quindi l'indirizzo si comporta come un secret, ma può fuoriuscire in modi ordinari: dalla cronologia della shell o dai file di configurazione eseguiti con commit in un repository git. L'autorizzazione del client elimina questa esposizione. Il servizio pubblica il proprio descriptor cifrato con una chiave del client, quindi chi dispone dell'indirizzo ma non della chiave non può nemmeno individuare il servizio.

Genera 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 un'installazione standard di Ubuntu non include. Il comando si interrompe quindi con base64pem: command not found. GNU base64 -d decodifica lo stesso corpo PEM, quindi usa quello.

Sul server, installa 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. Salvala come laptop.auth.txt: in caso contrario tor ignora il file senza stampare errori e il servizio rimane silenziosamente accessibile a chiunque disponga dell'indirizzo.

Sul client, installa la chiave privata. In Ubuntu, il demone tor viene eseguito come utente debian-tor e non può leggere i file nella tua home directory, quindi conserva 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

Aggiungi ClientOnionAuthDir /var/lib/tor/onion_auth a /etc/tor/torrc del client e ricarica tor. Se esegui tor con il tuo utente, ad esempio con la build Homebrew su macOS, imposta ClientOnionAuthDir su ~/.tor/onion_auth con modalità 0700.

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

Ora verifica entrambe le direzioni. ssh myvps dovrebbe continuare a connettersi. Da una macchina che non possiede alcuna chiave, lo stesso indirizzo dovrebbe non essere raggiungibile. Questo errore dimostra che l'autorizzazione è attiva.

Chiudere la porta 22, in quest’ordine

Impostare prima una rete di sicurezza. Questo comando annulla entrambe le modifiche riportate di seguito 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'

Annullarla con sudo systemctl stop ssh-rescue.timer dopo avere 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 quello pubblico. È il modo più comune in cui questo passaggio fallisce 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, usando 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 su porte come 443 e 9001, quindi una policy predefinita che nega il traffico in uscita impedisce il bootstrap di Tor e rimuove contemporaneamente l’unico accesso ancora disponibile. La maggior parte dei provider gestisce anche un firewall di rete separato nel pannello di controllo. Chiudere la porta 22 anche lì; in caso contrario la porta resta raggiungibile indipendentemente da quanto riportato da ufw.

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

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 di riavviare. 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 è operativa.

Se 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 di autorizzazioni della directory. Puoi anche verificare una modifica a torrc prima di applicarla.

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

Cosa 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 è composto da tre relay e il lato del servizio ne aggiunge altri tre. I caratteri digitati attraversano quindi circa sei macchine scelte casualmente in tutto il mondo. La digitazione interattiva presenta un ritardo evidente e le copie dei file sono lente. 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 e cambia quando tor ne costruisce un altro.

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

Precisione dell'orologio. I descrittori degli onion service vengono pubblicati in base a intervalli temporali. Un orologio molto impreciso impedisce quindi 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 del 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.

In pratica, la soluzione migliore è spesso usare entrambi. Utilizzate WireGuard come percorso quotidiano e mantenete l'onion service come percorso di emergenza, ancora disponibile quando la configurazione di WireGuard è errata. In questo modo lasciate aperta una porta UDP invece di una porta SSH pubblica. Nulla di tutto questo sostituisce la messa in sicurezza di sshd: l'autenticazione basata soltanto su chiavi e l'accesso con un account diverso da root restano importanti, perché un onion service protegge il percorso di rete e nient'altro.

Modalità di errore e messaggi visualizzati

Tor non supera mai Bootstrapped 0%. Il traffico in uscita è bloccato oppure l’orologio del sistema è molto fuori sincrono. Controllare la policy in uscita con sudo ufw status verbose, quindi eseguire timedatectl.

systemctl status tor restituisce active (exited). Su Debian e Ubuntu è normale. Consultare 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, operazione che richiede poco tempo dopo un reload, 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 usare. Verificare 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. Un = finale o un carattere di nuova riga estraneo all’interno della stringa base32 causa questo errore.

nc: invalid option -- 'X'. È installato GNU netcat anziché quello OpenBSD. Eseguire sudo apt install -y netcat-openbsd.

Could not resolve hostname. ssh ha tentato una normale risoluzione DNS, che non restituisce risultati per .onion, quindi 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 la propria attività. Gestire il problema come un normale problema di autorizzazione publickey negata e non coinvolgere tor.

FAQ

Un onion service implica davvero che sul mio VPS non ci siano porte aperte?

Sì, dopo aver associato sshd a 127.0.0.1 e aver configurato il firewall in modo che blocchi il traffico in ingresso. Tor stabilisce una connessione TCP in uscita verso un relay e la sessione torna indietro attraverso quel relay. Di conseguenza, nessun servizio sul server accetta connessioni sull'indirizzo pubblico. Verificalo con ss -tlnp sul server e con una scansione delle porte eseguita da un altro sistema. Non dimenticare il firewall di rete del provider, disponibile nel pannello di controllo. È un controllo separato da ufw e deve essere chiuso anch'esso.

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

No. L'indirizzo è composto da 56 caratteri e non può essere indovinato o enumerato tramite il sistema di directory. Si comporta quindi come un secret, ma può essere esposto dalla cronologia della shell e dai file di configurazione. Aggiungi l'autorizzazione client v3. In questo modo, il descrittore del servizio 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 motivo, devi verificare la console del provider prima di chiudere la porta 22. Tor ha inoltre bisogno di tempo per completare il bootstrap dopo l'avvio. Di conseguenza, l'indirizzo risponde più tardi rispetto al sistema ai ping. Se non risponde mai, accedi tramite la console e leggi sudo journalctl -u tor@default -b. Qui viene riportato un eventuale errore di sintassi in torrc o un problema 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 usa un unico hop cifrato diretto verso il server. La digitazione risulta poco reattiva e i trasferimenti sono lenti. Una configurazione comune prevede WireGuard per l'uso quotidiano e l'onion service come percorso di emergenza, in grado di funzionare anche quando la configurazione della VPN non è valida.