SSH przez Tor onion service bez otwartych portów
Konfiguracja SSH ukrytego za usługą onion sieci Tor. Instrukcja obejmuje autoryzację v3 oraz bezpieczną kolejność zmian, która zapobiega trwałej utracie dostępu do serwera VPS.
Co zmienia SSH przez usługę onion sieci Tor
SSH przez usługę onion sieci Tor umożliwia administrowanie serwerem VPS, który nie akceptuje żadnych połączeń przychodzących na żadnym porcie. Serwer nawiązuje połączenie z siecią Tor i utrzymuje je w stanie otwartym. Sesja SSH dociera do serwera tą samą drogą, dzięki czemu żaden proces nie musi nasłuchiwać na publicznym adresie IP.
Wpływ na dziennik zdarzeń jest natychmiastowy. Serwer z publicznym portem SSH rejestruje tysiące nieudanych prób logowania dziennie, pochodzących ze skanerów. Przeniesienie sshd za usługę onion i zablokowanie ruchu przychodzącego na firewallu sprawia, że /var/log/auth.log rejestruje od tego momentu wyłącznie sesje zainicjowane przez administratora.
Koszt tego rozwiązania polega na tym, że tor znajduje się na ścieżce każdej sesji administracyjnej. Jest to demon działający w przestrzeni użytkownika, który musi uruchomić się i zainicjować po każdym restarcie systemu, zanim możliwe będzie zalogowanie. Należy to uwzględnić przed zamknięciem portu, ponieważ w przypadku awarii można utracić dostęp do maszyny, do której nie ma się fizycznego dostępu.
Zapewnienie dostępu awaryjnego przed wprowadzeniem zmian
Nie należy rozpoczynać prac bez przygotowania ścieżki odzyskiwania, która nie wykorzystuje SSH.
Należy otworzyć konsolę dostawcy, czyli konsolę VNC lub szeregową w panelu sterowania, i zalogować się za jej pomocą. Jeśli hasło użytkownika root nie jest znane, należy najpierw zresetować hasło root z poziomu panelu i potwierdzić jego poprawność. Konsola, która nie została wcześniej przetestowana, nie stanowi skutecznej ścieżki odzyskiwania.
Kolejność poniższych kroków ma znaczenie. Każdy etap jest weryfikowany przed przejściem do kolejnego, a port 22 pozostaje otwarty do momentu poprawnego działania trasy onion.
- Zainstaluj tor i potwierdź, że proces bootstrap został zakończony.
- Zdefiniuj usługę onion i odczytaj jej adres.
- Połącz się przez sieć onion, podczas gdy port 22 jest nadal otwarty.
- Dodaj autoryzację klienta, a następnie połącz się ponownie.
- Powiąż
sshdz interfejsem loopback i zamknij port 22. - Zrestartuj system, a następnie połącz się ponownie przez sieć onion.
Bieżąca sesja SSH musi pozostać otwarta przez cały czas trwania procesu. Ustanowiona sesja przetrwa zmianę reguł zapory sieciowej, która zablokowałaby nowe połączenie, dlatego stanowi ona pierwszą linię ratunkową.
Instalacja tor na serwerze
Ubuntu dostarcza tor we własnym repozytorium, jednak ta wersja jest często nieaktualna. Repozytorium Tor Project zawiera wersję opisaną w ich dokumentacji. Należy je dodać za pomocą poleceń z ich przewodnika po repozytorium 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/nullWpisz /etc/apt/sources.list.d/tor.sources. Suites pobiera nazwę kodową wydania, którą wyświetla lsb_release -cs (noble w przypadku 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-pagerDziennik powinien kończyć się wpisem Bootstrapped 100% (done). Zatrzymanie się poniżej tego punktu oznacza, że tor nie może połączyć się z siecią, co niemal zawsze wynika z reguły firewalla wychodzącego lub nieprawidłowego ustawienia zegara systemowego.
Nazwa jednostki jest myląca. systemctl status tor zgłasza Active: active (exited) nawet wtedy, gdy wszystko działa poprawnie, ponieważ w systemach Debian i Ubuntu pakiet tor jest jednostką nadrzędną (master unit) dla wielu instancji, której jedynym zadaniem jest uruchomienie właściwej instancji. Sam demon działa jako tor@default.service. Używaj tej nazwy w poleceniach status oraz journalctl. Polecenia start, stop i reload wydane dla tor przekazują sygnały do instancji, więc sudo systemctl reload tor działa zgodnie z oczekiwaniami.
Definiowanie usługi onion dla portu 22
Dodaj dwie linie do /etc/tor/torrc.
HiddenServiceDir /var/lib/tor/ssh/
HiddenServicePort 22 127.0.0.1:22Druga linia instruuje tor, aby akceptował wirtualny port 22 pod adresem onion i łączył się z 127.0.0.1:22 na serwerze. Tor łączy się z sshd przez interfejs loopback, co pozwala na późniejsze wyłączenie nasłuchiwania sshd na publicznym adresie IP.
sudo systemctl reload tor
sudo cat /var/lib/tor/ssh/hostnamePolecenie to wyświetla 56 znaków w formacie base32, po których następuje .onion. Znaki te stanowią zakodowany klucz publiczny usługi. W tym modelu nie występuje urząd certyfikacji ani rejestracja nazw.
Pozwól, aby tor samodzielnie utworzył /var/lib/tor/ssh/. Ręczne utworzenie katalogu z niewłaściwym właścicielem lub uprawnieniami luźniejszymi niż 0700 spowoduje, że tor odmówi jego użycia, a dziennik systemowy zgłosi błąd zbyt szerokich uprawnień. Pliki wewnątrz katalogu stanowią tożsamość usługi: hs_ed25519_secret_key jest adresem. Wykonaj kopię zapasową tego katalogu z uprawnieniami 600 i przechowuj ją poza serwerem, ponieważ utrata tych plików oznacza konieczność wygenerowania nowego adresu i aktualizacji konfiguracji na każdym kliencie.
Połączenie ze stacji roboczej
Stacja robocza wymaga klienta sieci Tor, który nie wymaga żadnej konfiguracji. W systemach Debian lub Ubuntu jest to sudo apt install -y tor netcat-openbsd. Tor nasłuchuje następnie na 127.0.0.1:9050 jako proxy SOCKS5. SOCKS to ogólny protokół proxy, a wersja 5 pozwala na przesyłanie nazwy hosta zamiast adresu IP, co jest w tym przypadku kluczowe.
OpenSSH nie posiada własnego klienta SOCKS, dlatego do nawiązania połączenia wykorzystywany jest program pomocniczy. Należy dodać poniższą konfigurację do ~/.ssh/config.
Host myvps
HostName xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.onion
User admin
ProxyCommand /usr/bin/nc -X 5 -x 127.0.0.1:9050 %h %p
ServerAliveInterval 30Flaga -X 5 wybiera SOCKS5, a -x 127.0.0.1:9050 wskazuje na lokalną instancję Tor. %h przekazuje nazwę onion do sieci Tor, dzięki czemu Tor rozwiązuje ją wewnątrz swojej sieci. Wymagane jest użycie wersji OpenBSD netcat. Wersja GNU netcat nie posiada opcji -X i kończy działanie błędem nc: invalid option -- 'X'.
ssh myvpsPierwsze połączenie jest powolne, ponieważ Tor musi najpierw zbudować obwód (circuit). Odcisk palca klucza hosta należy zaakceptować w standardowy sposób. Od tego momentu obowiązują standardowe zasady obsługi kluczy SSH. Zmienił się jedynie transport, a nie proces uwierzytelniania.
W przypadku jednorazowego połączenia można pominąć wpis w konfiguracji: polecenie torsocks ssh admin@xxxxx.onion wykonuje to samo zadanie.
Dodawanie autoryzacji klienta v3
W obecnej konfiguracji każdy, kto pozna adres, może połączyć się z banerem SSH i rozpocząć próby odgadywania hasła. Adresy Onion nie są wymienione w systemie katalogów, więc adres sam w sobie pełni rolę sekretu, jednak może wyciec w typowy sposób: poprzez historię powłoki lub pliki konfiguracyjne zatwierdzone w repozytorium git. Autoryzacja klienta eliminuje to ryzyko. Usługa publikuje swój deskryptor zaszyfrowany kluczem klienta, dzięki czemu osoba posiadająca adres, ale nieposiadająca klucza, nie jest w stanie nawet zlokalizować usługi.
Wygeneruj parę kluczy x25519 po stronie klienta. Poniżej znajduje się potok poleceń pochodzący z przewodnika autoryzacji klienta projektu Tor, z jedną modyfikacją.
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.keyOpublikowana wersja tych linii wykorzystuje base64pem -d, którego standardowa instalacja Ubuntu nie zawiera. Polecenie kończy się wtedy błędem base64pem: command not found. GNU base64 -d dekoduje ten sam korpus PEM, dlatego należy użyć tego narzędzia.
Na serwerze zainstaluj klucz publiczny.
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 torOdczytywane są wyłącznie pliki kończące się na .auth. Zapisanie pliku jako laptop.auth.txt spowoduje, że tor zignoruje go bez wyświetlenia błędu, a usługa pozostanie dostępna dla każdego, kto zna adres.
Na kliencie zainstaluj klucz prywatny. W systemie Ubuntu demon tor działa jako użytkownik debian-tor i nie ma uprawnień do odczytu plików w katalogu domowym użytkownika, dlatego należy umieścić katalog w miejscu dostępnym dla tego użytkownika.
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_privateDodaj ClientOnionAuthDir /var/lib/tor/onion_auth do pliku /etc/tor/torrc klienta i przeładuj usługę tor. Jeśli tor działa na koncie użytkownika (na przykład w wersji Homebrew na systemie macOS), wskaż ClientOnionAuthDir na ~/.tor/onion_auth z uprawnieniami 0700.
Adres wewnątrz tego pliku to 56 znaków bez przyrostka .onion. Po zakończeniu usuń /tmp/k1.prv.pem oraz /tmp/k1.prv.key.
Teraz przetestuj oba kierunki. Polecenie ssh myvps powinno nadal nawiązywać połączenie. Z maszyny nieposiadającej klucza połączenie z tym samym adresem powinno zakończyć się niepowodzeniem. To niepowodzenie jest dowodem na to, że autoryzacja jest aktywna.
Zamknięcie portu 22 w określonej kolejności
Najpierw należy ustawić zabezpieczenie. Poniższe polecenie cofnie obie zmiany po upływie piętnastu minut, jeśli użytkownik zostanie odcięty od serwera.
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'Anuluj to polecenie za pomocą sudo systemctl stop ssh-rescue.timer po potwierdzeniu, że połączenie przez sieć onion nadal działa.
Następnie należy zatrzymać nasłuchiwanie sshd na publicznym adresie IP. System Ubuntu 24.04 aktywuje ssh poprzez jednostkę typu socket, dlatego ListenAddress w pliku sshd_config jest ignorowane: ssh.socket zarządza gniazdem nasłuchującym, a nie sshd. Sprawdź, który przypadek dotyczy Twojej konfiguracji.
systemctl is-enabled ssh.socketJeśli polecenie zwróci enabled, uruchom sudo systemctl edit ssh.socket i dodaj poniższą treść.
[Socket]
ListenStream=
ListenStream=127.0.0.1:22Pusta wartość ListenStream= czyści wartość odziedziczoną z dostarczonej jednostki. Pominięcie tej linii spowoduje dodanie drugiego gniazda nasłuchującego przy jednoczesnym zachowaniu publicznego, co jest najczęstszą przyczyną niepowodzenia tego kroku bez wyświetlenia komunikatu o błędzie.
sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
ss -tlnp | grep ':22'ss powinno wyświetlić 127.0.0.1:22 i brak wpisów dla 0.0.0.0:22. Jeśli ssh.socket było wyłączone, umieść ListenAddress 127.0.0.1 w /etc/ssh/sshd_config.d/10-onion.conf, uruchom sudo systemctl restart ssh, a następnie sprawdź wynik za pomocą tego samego polecenia ss. Ten wynik stanowi potwierdzenie w obu przypadkach.
Następnie należy skonfigurować zaporę sieciową, co jest standardową procedurą zarządzania regułami ufw na VPS. Uruchom najpierw sudo ufw status numbered i usuń regułę SSH, która zostanie wyświetlona na liście.
sudo ufw status numbered
sudo ufw delete allow OpenSSH
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw status verbosePozostaw ruch wychodzący dozwolony. Tor łączy się z przekaźnikami na portach takich jak 443 i 9001, więc polityka domyślnego blokowania ruchu wychodzącego (default-deny) uniemożliwi proces bootstrapu sieci Tor i jednocześnie usunie jedyną pozostałą drogę dostępu do serwera. Większość dostawców oferuje również oddzielną zaporę sieciową w panelu sterowania. Zamknij port 22 również tam, w przeciwnym razie port pozostanie dostępny niezależnie od tego, co raportuje ufw.
Jeśli na serwerze działa Docker, sprawdź opublikowane porty przed zakończeniem prac. Docker zapisuje własne reguły bezpośrednio do tych samych tablic i publikuje porty kontenerów z pominięciem ufw, więc polityka blokowania ufw nie daje pełnego obrazu sytuacji.
Zrestartuj przed zaufaniem usłudze
systemctl is-enabled tor@default
sudo rebootJeśli pierwsze polecenie nie wskazuje, że usługa jest włączona, wykonaj sudo systemctl enable tor@default przed restartem systemu. Odczekaj dwie minuty, a następnie wykonaj ssh myvps. Tor wymaga czasu na bootstrap po uruchomieniu, więc adres onion zaczyna odpowiadać dopiero po pewnym czasie od startu maszyny.
Jeśli usługa nie powraca do działania, otwórz konsolę i odczytaj sudo journalctl -u tor@default -b. Znajdują się tam informacje o błędach składni w pliku torrc lub problemach z uprawnieniami do katalogów. Przed zastosowaniem zmian w pliku torrc warto również zweryfikować jego poprawność.
sudo -u debian-tor tor --verify-configKoszty rozwiązania w porównaniu z tunelem WireGuard
W zestawieniu z własnym VPN WireGuard na VPS, usługa onion jest wolniejsza i mniej przewidywalna. Przed podjęciem decyzji należy uczciwie ocenić różnice między tymi rozwiązaniami.
Opóźnienia. Obwód klienta składa się z trzech przekaźników, a strona usługi dodaje kolejne trzy, więc przesyłane dane przechodzą przez około sześć losowo wybranych maszyn na całym świecie. Interaktywne wpisywanie tekstu wiąże się z widocznym opóźnieniem, a kopiowanie plików jest powolne. WireGuard dodaje tylko jeden przeskok. Warto zmierzyć opóźnienia w konkretnym przypadku za pomocą time ssh myvps 'echo ok', ponieważ wynik zależy od obwodu zbudowanego przez tor i zmienia się przy każdej jego rekonfiguracji.
Demon w przestrzeni użytkownika na ścieżce krytycznej. WireGuard działa w jądrze systemu i uruchamia się wraz z siecią. Tor jest procesem, który musi wystartować, przeprowadzić bootstrap i połączyć się z przekaźnikiem wejściowym (guard relay), zanim jakakolwiek komunikacja stanie się możliwa. W przypadku awarii konieczne jest skorzystanie z konsoli dostawcy.
Dokładność zegara. Deskryptory usług onion są publikowane w oparciu o przedziały czasowe, więc nieprawidłowe ustawienie zegara uniemożliwia wyszukiwanie adresów bez wyświetlenia jasnego komunikatu o błędzie. timedatectl powinno zwracać System clock synchronized: yes.
Zaletą tego rozwiązania jest odporność na błędy w regułach firewalla. Brak otwartych portów do skanowania i banerów do przechwycenia, a sam adres jest kluczem publicznym, dzięki czemu punkt końcowy potwierdza swoją tożsamość jeszcze przed nawiązaniem połączenia SSH.
W praktyce zazwyczaj stosuje się oba rozwiązania jednocześnie. WireGuard służy jako codzienna ścieżka dostępu, a usługa onion pozostaje drogą awaryjną, działającą nawet przy błędnej konfiguracji WireGuard. Pozwala to na pozostawienie otwartego tylko jednego portu UDP zamiast publicznego portu SSH. Żadne z tych rozwiązań nie zastępuje utwardzenia samego sshd: uwierzytelnianie wyłącznie za pomocą kluczy oraz logowanie na konto inne niż root pozostają kluczowe, ponieważ usługa onion chroni jedynie ścieżkę sieciową, a nie to, co znajduje się za nią.
Tryby awarii i komunikaty błędów
Tor nigdy nie przechodzi przez Bootstrapped 0%. Ruch wychodzący jest blokowany lub zegar systemowy jest znacznie rozsynchronizowany. Należy sprawdzić politykę ruchu wychodzącego za pomocą sudo ufw status verbose, a następnie uruchomić timedatectl.
systemctl status tor zwraca active (exited). Jest to zachowanie standardowe w systemach Debian i Ubuntu. Należy zamiast tego zapoznać się z tor@default.
Nie można odnaleźć deskryptora. Tor zwraca rozszerzony błąd SOCKS F0, "Onion Service Descriptor Can Not be Found". Deskryptor nie został jeszcze opublikowany, co zajmuje chwilę po przeładowaniu konfiguracji, lub proces tor na serwerze nie działa.
F4, "Onion Service Missing Client Authorization". Klient nie posiada pasującego pliku .auth_private, którego tor mógłby użyć. Należy sprawdzić, czy ClientOnionAuthDir znajduje się w pliku torrc, czy katalog posiada uprawnienia 0700, czy nazwa pliku kończy się na .auth_private oraz czy użytkownik debian-tor ma uprawnienia do jego odczytu.
F5, "Onion Service Wrong Client Authorization". Klucz prywatny nie pasuje do pliku .auth na serwerze. Przyczyną jest często znak = na końcu linii lub zbędny znak nowej linii wewnątrz ciągu base32.
nc: invalid option -- 'X'. Zainstalowano GNU netcat zamiast wersji OpenBSD. Należy uruchomić sudo apt install -y netcat-openbsd.
Could not resolve hostname. ssh podjęło próbę użycia standardowego DNS, który nie posiada rekordu dla .onion, przez co ProxyCommand nie zostało wykonane. Wzorzec Host w pliku ~/.ssh/config nie pasuje do wprowadzonej nazwy.
Permission denied (publickey). Tunel działa poprawnie i rola tor została zakończona. Należy potraktować to jako standardowy problem z odmową dostępu przy uwierzytelnianiu kluczem publicznym i pominąć tor w dalszej diagnostyce.
FAQ
Czy usługa onion faktycznie oznacza brak otwartych portów na VPS?
Tak, pod warunkiem, że sshd jest powiązany z 127.0.0.1, a firewall odrzuca ruch przychodzący. Tor nawiązuje wychodzące połączenie TCP do przekaźnika, a sesja wraca tą samą drogą, więc żaden proces na serwerze nie akceptuje połączeń na publicznym adresie. Można to zweryfikować za pomocą ss -tlnp na serwerze oraz skanowania portów z zewnątrz. Należy pamiętać o sieciowym firewallu dostawcy w panelu sterowania, który jest niezależny od ufw i również musi zostać zamknięty.
Czy adres .onion sam w sobie zapewnia wystarczające bezpieczeństwo dla SSH?
Nie. Adres składa się z 56 znaków i nie można go odgadnąć ani wyliczyć z systemu katalogów, więc działa jak sekret, ale wycieka przez historię powłoki i pliki konfiguracyjne. Należy dodać autoryzację klienta v3. Dzięki niej deskryptor usługi jest szyfrowany kluczem klienta, więc osoba posiadająca tylko adres otrzyma błąd rozszerzony F4 i w ogóle nie dotrze do sshd.
Co się stanie, jeśli tor nie uruchomi się po restarcie?
Utracisz dostęp SSH, ponieważ adres onion jest wtedy jedyną drogą wejścia. Dlatego konsola dostawcy musi zostać przetestowana przed zamknięciem portu 22. Tor potrzebuje również czasu na bootstrap po uruchomieniu, więc adres odpowiada później niż maszyna reaguje na ping. Jeśli nigdy nie odpowiada, zaloguj się przez konsolę i odczytaj sudo journalctl -u tor@default -b, gdzie zapisywany jest błąd składni torrc lub problem z uprawnieniami do /var/lib/tor/ssh.
Czy SSH przez Tor jest wolniejsze niż WireGuard?
Tak, znacznie. Połączenie z usługą onion przechodzi przez około sześć losowo wybranych przekaźników, podczas gdy WireGuard to jeden szyfrowany przeskok bezpośrednio do serwera. Pisanie jest odczuwalnie opóźnione, a transfery wolne. Typowa konfiguracja to WireGuard do codziennej pracy, z usługą onion utrzymywaną jako awaryjna ścieżka dostępu, która działa nawet przy błędnej konfiguracji VPN.