SSH über Tor-Onion-Service ohne offene Ports
Betreiben Sie sshd hinter einem Tor-Onion-Service: VPS ohne eingehende Ports, inklusive v3-Client-Autorisierung und der sicheren Reihenfolge gegen Aussperrung.
Änderungen bei SSH über einen Tor-Onion-Service
SSH über einen Tor-Onion-Service ermöglicht die Verwaltung eines VPS, der an keinem Port eingehende Verbindungen akzeptiert. Der Server baut die Verbindung zum Tor-Netzwerk ausgehend auf und hält sie offen. Ihre SSH-Sitzung wird über diese Verbindung zurückgeleitet. Daher muss an der öffentlichen IP-Adresse nichts auf Verbindungen warten.
Die Auswirkung auf das Protokoll ist sofort erkennbar. Ein System mit einem öffentlichen SSH-Port verzeichnet durch Scanner täglich Tausende fehlgeschlagene Anmeldeversuche mit Passwörtern. Wenn Sie sshd hinter einem Onion-Service betreiben und eingehenden Datenverkehr an der Firewall verwerfen, protokolliert /var/log/auth.log anschließend nur noch die von Ihnen gestarteten Sitzungen.
Der Nachteil ist, dass tor sich im Pfad jeder Administrationssitzung befindet. Es handelt sich um einen Daemon im Userspace, der nach jedem Reboot gestartet werden und den Verbindungsaufbau abschließen muss, bevor Sie sich anmelden können. Planen Sie dies, bevor Sie den Port schließen. Andernfalls können Sie den Zugriff auf ein System verlieren, das physisch nicht erreichbar ist.
Schaffen Sie sich einen Rückweg, bevor Sie etwas ändern
Beginnen Sie erst, wenn Sie über einen Wiederherstellungsweg verfügen, der nicht auf SSH angewiesen ist.
Öffnen Sie jetzt die Konsole Ihres Providers, also die VNC- oder serielle Konsole im Control Panel, und melden Sie sich darüber an. Wenn das root-Passwort unbekannt ist, setzen Sie das root-Passwort zuerst über das Panel zurück und bestätigen Sie, dass die Anmeldung funktioniert. Eine Konsole, die Sie noch nie getestet haben, ist kein Wiederherstellungsweg.
Die folgende Reihenfolge ist wichtig. Jeder Schritt wird überprüft, bevor der nächste ausgeführt wird. Port 22 bleibt geöffnet, bis die Onion-Route funktioniert.
- Installieren Sie tor und bestätigen Sie, dass der Bootstrap-Vorgang erfolgreich abgeschlossen wird.
- Definieren Sie den Onion-Service und lesen Sie die Adresse aus.
- Stellen Sie eine Verbindung über den Onion-Service her, solange Port 22 noch geöffnet ist.
- Fügen Sie die Client-Autorisierung hinzu und stellen Sie anschließend erneut eine Verbindung her.
- Binden Sie
sshdan das Loopback-Interface und schließen Sie Port 22. - Starten Sie den Server neu und stellen Sie anschließend erneut eine Verbindung über den Onion-Service her.
Lassen Sie Ihre aktuelle SSH-Sitzung während des gesamten Vorgangs geöffnet. Eine bestehende Sitzung bleibt auch dann erhalten, wenn eine Firewall-Änderung neue Verbindungen blockieren würde. Sie ist daher Ihre erste Möglichkeit zur Wiederherstellung.
Tor auf dem Server installieren
Ubuntu liefert tor im eigenen Repository aus, aber diese Version ist häufig veraltet. Das Repository des Tor Project enthält die Version, die in der Dokumentation beschrieben wird. Fügen Sie es mit den Befehlen aus der apt-Repository-Anleitung hinzu.
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/nullGeben Sie /etc/apt/sources.list.d/tor.sources ein. Suites übernimmt den Release-Codenamen, den lsb_release -cs ausgibt (noble unter 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.gpgsudo apt update
sudo apt install -y tor deb.torproject.org-keyring
sudo journalctl -u tor@default -n 20 --no-pagerDas Log sollte mit Bootstrapped 100% (done) enden. Wenn der Vorgang dort hängen bleibt, kann tor das Netzwerk nicht erreichen. Fast immer liegt das an einer ausgehenden Firewall-Regel oder einer stark falschen Systemzeit.
Der Name der Unit ist eine Falle. systemctl status tor meldet auch bei einem fehlerfreien Zustand Active: active (exited), weil Debian und Ubuntu tor als Multi-Instance-Master-Unit paketieren. Ihre einzige Aufgabe besteht darin, die tatsächliche Instanz zu laden. Der Daemon läuft selbst als tor@default.service. Verwenden Sie diesen Namen für status und journalctl. Starten, Stoppen und Neuladen von tor erreichen die Instanz dennoch, sodass sudo systemctl reload tor wie erwartet funktioniert.
Onion-Dienst für Port 22 definieren
Fügen Sie /etc/tor/torrc zwei Zeilen hinzu.
HiddenServiceDir /var/lib/tor/ssh/
HiddenServicePort 22 127.0.0.1:22Die zweite Zeile weist tor an, den virtuellen Port 22 unter der Onion-Adresse anzunehmen und eine Verbindung zu 127.0.0.1:22 auf dem Server herzustellen. Tor erreicht sshd über das Loopback-Interface. Genau deshalb kann sshd später auf der öffentlichen Adresse nicht mehr auf Verbindungen warten.
sudo systemctl reload tor
sudo cat /var/lib/tor/ssh/hostnameDieser Befehl gibt 56 Base32-Zeichen gefolgt von .onion aus. Diese Zeichen sind der codierte öffentliche Schlüssel des Dienstes. Es gibt dabei weder eine Zertifizierungsstelle noch eine Namensregistrierung.
Lassen Sie tor /var/lib/tor/ssh/ selbst erstellen. Wenn Sie das Verzeichnis manuell mit dem falschen Eigentümer oder mit einem weniger restriktiven Modus als 0700 anlegen, verweigert tor dessen Verwendung. Im Journal wird das Verzeichnis dann als zu weit freigegeben gemeldet. Die Dateien darin bilden die Identität des Dienstes: hs_ed25519_secret_key ist die Adresse. Sichern Sie dieses Verzeichnis mit dem Modus 600 und bewahren Sie die Kopie außerhalb des Servers auf. Wenn es verloren geht, benötigen Sie eine neue Adresse und müssen die Konfiguration auf jedem Client ändern.
Verbindung von Ihrem Arbeitsplatz herstellen
Auf Ihrem Arbeitsplatz wird ein Tor-Client benötigt. Dafür ist keine Konfiguration erforderlich. Unter Debian oder Ubuntu ist das sudo apt install -y tor netcat-openbsd. Tor lauscht anschließend auf 127.0.0.1:9050 als SOCKS5-Proxy. SOCKS ist ein generisches Proxy-Protokoll. Version 5 kann statt einer IP-Adresse einen Hostnamen übertragen. Das ist hier entscheidend.
OpenSSH hat keinen eigenen SOCKS-Client. Daher stellt ein Hilfsprogramm die Verbindung her. Fügen Sie Folgendes in ~/.ssh/config ein.
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 wählt SOCKS5 aus. -x 127.0.0.1:9050 verweist auf den lokalen Tor-Dienst. %h übergibt den Onion-Namen als Namen an Tor. Dadurch löst Tor ihn innerhalb des Netzwerks auf. Dafür muss es sich um OpenBSD netcat handeln. GNU netcat unterstützt die Option -X nicht und beendet sich mit nc: invalid option -- 'X'.
ssh myvpsDie erste Verbindung ist langsam, weil Tor zunächst einen Circuit aufbaut. Akzeptieren Sie den Fingerabdruck des Hostschlüssels wie bei jeder anderen Verbindung. Danach gilt die übliche SSH-Schlüsselverwaltung unverändert. Der Transportweg hat sich geändert. Die Authentifizierung nicht.
Für eine einmalige Verbindung können Sie den Konfigurationseintrag überspringen: torsocks ssh admin@xxxxx.onion erledigt dasselbe.
Client-Autorisierung für v3 hinzufügen
Derzeit kann jeder, der die Adresse kennt, das SSH-Banner erreichen und mit Anmeldeversuchen beginnen. Onion-Adressen können über das Verzeichnissystem nicht aufgelistet werden. Die Adresse verhält sich daher wie ein Geheimnis. Sie kann aber auf gewöhnlichem Weg offengelegt werden, etwa durch die Shell-History oder durch Konfigurationsdateien, die in ein Git-Repository übertragen wurden. Die Client-Autorisierung schließt diese Lücke. Der Dienst veröffentlicht seinen Descriptor verschlüsselt für einen Client-Schlüssel. Wer nur die Adresse, aber keinen Schlüssel besitzt, kann den Dienst nicht einmal auffinden.
Generieren Sie auf dem Client ein x25519-Schlüsselpaar. Dies ist die Pipeline aus dem Leitfaden des Tor Project zur Client-Autorisierung, mit einer Änderung.
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.keyIn der veröffentlichten Version dieser Zeilen wird base64pem -d verwendet. Eine Standardinstallation von Ubuntu enthält dieses Programm nicht. Der Befehl bricht dann mit base64pem: command not found ab. GNU base64 -d dekodiert denselben PEM-Body. Verwenden Sie daher stattdessen dieses Programm.
Installieren Sie auf dem Server den öffentlichen Schlüssel.
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 torEs werden nur Dateien gelesen, die auf .auth enden. Speichern Sie den Schlüssel als laptop.auth.txt. Andernfalls ignoriert tor die Datei ohne ausgegebene Fehlermeldung. Der Dienst bleibt dann weiterhin für jeden offen, der die Adresse kennt.
Installieren Sie auf dem Client den privaten Schlüssel. Unter Ubuntu läuft der tor-Daemon als Benutzer debian-tor und kann keine Dateien in Ihrem Home-Verzeichnis lesen. Speichern Sie das Verzeichnis daher an einem Ort, auf den dieser Benutzer zugreifen kann.
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_privateFügen Sie ClientOnionAuthDir /var/lib/tor/onion_auth zur /etc/tor/torrc des Clients hinzu und laden Sie tor neu. Wenn Sie tor stattdessen als eigener Benutzer ausführen, beispielsweise den Homebrew-Build unter macOS, verweisen Sie ClientOnionAuthDir mit dem Modus 0700 auf ~/.tor/onion_auth.
Die Adresse in dieser Datei besteht aus 56 Zeichen ohne das Suffix .onion. Löschen Sie /tmp/k1.prv.pem und /tmp/k1.prv.key, sobald Sie fertig sind.
Testen Sie nun beide Richtungen. ssh myvps sollte weiterhin eine Verbindung herstellen. Von einem Computer ohne Schlüssel sollte dieselbe Adresse fehlschlagen. Dieser Fehler bestätigt, dass die Autorisierung aktiv ist.
Port 22 in dieser Reihenfolge schließen
Richten Sie zuerst ein Sicherheitsnetz ein. Dieser eine Befehl macht beide folgenden Änderungen nach fünfzehn Minuten rückgängig, falls Sie sich aussperren.
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'Brechen Sie den Timer mit sudo systemctl stop ssh-rescue.timer ab, sobald Sie bestätigt haben, dass die Onion-Route weiterhin funktioniert.
Stoppen Sie als Nächstes, dass sshd an der öffentlichen Adresse lauscht. Ubuntu 24.04 aktiviert SSH über eine Socket-Unit. Daher wird ListenAddress in sshd_config ignoriert: ssh.socket verwaltet den Listening-Socket, nicht sshd. Prüfen Sie, welcher Fall bei Ihnen vorliegt.
systemctl is-enabled ssh.socketWenn dort enabled ausgegeben wird, führen Sie sudo systemctl edit ssh.socket aus und fügen Sie Folgendes hinzu.
[Socket]
ListenStream=
ListenStream=127.0.0.1:22Das leere ListenStream= löscht den Wert, der von der Paket-Unit übernommen wurde. Lassen Sie diese Zeile weg, fügen Sie einen zweiten Listener hinzu und behalten gleichzeitig den öffentlichen Listener bei. Das ist die häufigste Ursache dafür, dass dieser Schritt unbemerkt fehlschlägt.
sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
ss -tlnp | grep ':22'ss sollte 127.0.0.1:22 und nichts auf 0.0.0.0:22 anzeigen. Wenn ssh.socket deaktiviert war, tragen Sie ListenAddress 127.0.0.1 in /etc/ssh/sshd_config.d/10-onion.conf ein, führen Sie sudo systemctl restart ssh aus und prüfen Sie anschließend mit derselben ss-Zeile. Diese Ausgabe ist in beiden Fällen der Nachweis.
Anschließend folgt die Firewall, also die gewöhnliche Verwaltung von ufw-Regeln auf einem VPS. Führen Sie zuerst sudo ufw status numbered aus und löschen Sie die dort aufgeführte SSH-Regel.
sudo ufw status numbered
sudo ufw delete allow OpenSSH
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw status verboseLassen Sie ausgehenden Datenverkehr zu. Tor verbindet sich ausgehend mit Relays an Ports wie 443 und 9001. Eine standardmäßige Deny-Regel für ausgehenden Datenverkehr verhindert daher den Bootstrap von Tor und beseitigt gleichzeitig Ihre einzige verbleibende Zugangsmöglichkeit. Die meisten Anbieter betreiben zusätzlich eine separate Netzwerk-Firewall im Control Panel. Schließen Sie Port 22 auch dort. Andernfalls bleibt der Port erreichbar, unabhängig davon, was ufw meldet.
Wenn Docker auf diesem Server läuft, prüfen Sie die veröffentlichten Ports, bevor Sie den Vorgang als abgeschlossen betrachten. Docker schreibt eigene Regeln in dieselben Tabellen und veröffentlicht Container-Ports direkt an ufw vorbei. Eine ufw-Deny-Regel bildet daher nicht das vollständige Bild ab.
Vor dem Vertrauen neu starten
systemctl is-enabled tor@default
sudo rebootWenn der erste Befehl den Dienst nicht als aktiviert meldet, führen Sie vor dem Neustart sudo systemctl enable tor@default aus. Warten Sie zwei Minuten und führen Sie anschließend ssh myvps aus. Tor muss nach dem Booten den Bootstrap-Vorgang abschließen. Daher antwortet die Onion-Adresse erst einige Zeit nach dem Start der Maschine.
Wenn der Dienst nie wieder startet, öffnen Sie die Konsole und lesen Sie sudo journalctl -u tor@default -b. Dort werden Syntaxfehler in torrc oder ein Berechtigungsproblem mit einem Verzeichnis ausgegeben. Sie können eine Änderung an torrc auch vor der Anwendung prüfen.
sudo -u debian-tor tor --verify-configWas das im Vergleich zu einem WireGuard-Tunnel kostet
Im Vergleich zu einem WireGuard-VPN auf Ihrem eigenen VPS ist ein Onion Service langsamer und weniger vorhersehbar. Machen Sie sich die Nachteile bewusst, bevor Sie sich dafür entscheiden.
Latenz. Ein Client-Circuit besteht aus drei Relays. Die Serverseite fügt weitere drei hinzu. Ihre Tastatureingaben durchlaufen also ungefähr sechs zufällig ausgewählte Rechner auf der ganzen Welt. Beim interaktiven Tippen ist die Verzögerung deutlich spürbar. Dateiübertragungen sind langsam. WireGuard fügt nur einen Hop hinzu. Messen Sie Ihren eigenen Fall mit time ssh myvps 'echo ok', da der Wert davon abhängt, welchen Circuit tor gerade aufgebaut hat. Er ändert sich, sobald tor einen anderen Circuit aufbaut.
Ein Userspace-Daemon im kritischen Pfad. WireGuard läuft im Kernel und wird zusammen mit dem Netzwerk aktiviert. Tor ist ein Prozess, der starten, den Bootstrap durchführen und ein Guard Relay erreichen muss, bevor etwas funktioniert. Wenn das fehlschlägt, benötigen Sie die Provider-Konsole.
Genauigkeit der Systemzeit. Onion-Service-Deskriptoren werden für bestimmte Zeiträume veröffentlicht. Eine stark falsche Systemzeit verhindert daher die Adressauflösung, ohne dass irgendwo eine eindeutige Fehlermeldung erscheint. timedatectl sollte System clock synchronized: yes melden.
Dafür erhalten Sie eine Erreichbarkeit, die nicht mehr davon abhängt, dass eine Firewall-Regel korrekt ist. Es gibt keinen Port, der gescannt werden kann, und kein Banner, das sich auslesen lässt. Außerdem ist die Adresse selbst ein öffentlicher Schlüssel. Der Endpunkt weist seine Identität daher nach, bevor SSH überhaupt startet.
In der Praxis ist meist beides sinnvoll. Verwenden Sie WireGuard als täglichen Zugangsweg. Behalten Sie den Onion Service als Route, die weiterhin funktioniert, wenn die WireGuard-Konfiguration fehlerhaft ist. Dadurch bleibt nur ein UDP-Port offen und kein öffentlicher SSH-Port. Nichts davon ersetzt die Absicherung von sshd selbst: Die Authentifizierung ausschließlich per Schlüssel und eine Anmeldung ohne root bleiben wichtig, weil ein Onion Service den Netzwerkpfad schützt, aber nichts darüber hinaus.
Fehlerzustände und die dabei angezeigten Fehlermeldungen
Tor erreicht Bootstrapped 0% nie. Der ausgehende Verkehr wird blockiert, oder die Systemzeit weicht stark ab. Prüfen Sie die Richtlinie für ausgehenden Verkehr mit sudo ufw status verbose und führen Sie anschließend timedatectl aus.
systemctl status tor meldet active (exited). Das ist unter Debian und Ubuntu normal. Lesen Sie stattdessen tor@default.
Der Descriptor wurde nicht gefunden. Tor gibt den erweiterten SOCKS-Fehler F0, „Onion Service Descriptor Can Not be Found“, zurück. Entweder wurde der Descriptor noch nicht veröffentlicht, was nach einem Reload kurze Zeit dauert, oder tor läuft auf dem Server nicht.
F4, „Onion Service Missing Client Authorization“. Auf dem Client ist kein passendes .auth_private vorhanden, das tor verwenden kann. Prüfen Sie, ob ClientOnionAuthDir in torrc eingetragen ist, das Verzeichnis den Modus 0700 hat, der Dateiname mit .auth_private endet und debian-tor die Datei lesen kann.
F5, „Onion Service Wrong Client Authorization“. Der private Schlüssel passt nicht zur .auth-Datei auf dem Server. Ein abschließendes = oder ein zusätzlicher Zeilenumbruch innerhalb der Base32-Zeichenfolge verursacht diesen Fehler.
nc: invalid option -- 'X'. Anstelle der OpenBSD-Version ist GNU netcat installiert. Führen Sie sudo apt install -y netcat-openbsd aus.
Could not resolve hostname. ssh hat eine gewöhnliche DNS-Auflösung versucht. Dafür gibt es keine Antwort für .onion, daher wurde ProxyCommand nie ausgeführt. Das Muster Host in ~/.ssh/config passt nicht zu dem von Ihnen eingegebenen Namen.
Permission denied (publickey). Der Tunnel hat funktioniert und tor ist fertig. Behandeln Sie dies als gewöhnliches publickey-Problem mit verweigerter Berechtigung und berücksichtigen Sie tor dabei nicht.
FAQ
Bedeutet ein Onion Service wirklich, dass auf meinem VPS keine offenen Ports vorhanden sind?
Ja, sobald sshd an 127.0.0.1 gebunden ist und die Firewall eingehenden Datenverkehr verwirft. Tor stellt eine ausgehende TCP-Verbindung zu einem Relay her. Ihre Sitzung wird darüber zurückgeleitet. Dadurch akzeptiert auf dem System nichts eine Verbindung über die öffentliche Adresse. Überprüfen Sie das mit ss -tlnp auf dem Server und mit einem Portscan von einem anderen System aus. Vergessen Sie nicht die eigene Netzwerk-Firewall des Providers im Control Panel. Sie ist von ufw getrennt und muss ebenfalls geschlossen sein.
Bietet die .onion-Adresse allein ausreichende Sicherheit für SSH?
Nein. Die Adresse ist 56 Zeichen lang und kann nicht über das Verzeichnissystem erraten oder aufgelistet werden. Sie verhält sich daher wie ein Geheimnis. Sie kann jedoch in der Shell-Historie und in Konfigurationsdateien offengelegt werden. Fügen Sie die v3-Clientautorisierung hinzu. Damit wird der Service-Descriptor für Ihren Clientschlüssel verschlüsselt. Wer nur die Adresse besitzt, erhält den erweiterten Fehler F4 und erreicht sshd überhaupt nicht.
Was passiert, wenn Tor nach einem Reboot nicht startet?
Sie verlieren den SSH-Zugriff vollständig, weil die Onion-Adresse dann der einzige Zugangsweg ist. Deshalb muss die Provider-Konsole getestet werden, bevor Sie Port 22 schließen. Tor benötigt nach dem Boot außerdem Zeit für den Bootstrap-Vorgang. Daher antwortet die Adresse später, als das System auf Ping reagiert. Wenn sie nie antwortet, melden Sie sich über die Konsole an und lesen Sie sudo journalctl -u tor@default -b. Dort wird entweder ein Syntaxfehler in torrc oder ein Berechtigungsproblem bei /var/lib/tor/ssh ausgegeben.
Ist SSH über Tor langsamer als WireGuard?
Ja, deutlich. Eine Verbindung zu einem Onion Service durchläuft etwa sechs zufällig ausgewählte Relays. WireGuard verwendet dagegen nur einen verschlüsselten Hop direkt zu Ihrem Server. Die Eingabe reagiert verzögert, und Übertragungen sind langsam. Häufig wird WireGuard für die tägliche Arbeit verwendet. Der Onion Service bleibt als Notfallzugang bestehen, der auch bei einer fehlerhaften VPN-Konfiguration verfügbar ist.