Настройка SSH через Tor onion-сервис без открытия портов
Узнайте, как скрыть SSH-сервер за Tor onion-сервисом для защиты VPS от сканеров. Инструкция по настройке v3 авторизации и последовательность действий для предотвращения потери доступа.
Что меняет использование SSH через onion-сервис Tor
SSH через onion-сервис Tor позволяет администрировать VPS, который не принимает входящие соединения ни на один порт. Сервер устанавливает исходящее соединение с сетью Tor и поддерживает его в открытом состоянии. Ваша SSH-сессия проходит через этот канал, поэтому на публичном IP-адресе не требуется открывать порты для прослушивания.
Эффект для логов проявляется мгновенно. Сервер с открытым публичным SSH-портом ежедневно собирает тысячи попыток подбора пароля от сканеров. Если переместить sshd за onion-сервис и запретить входящий трафик на фаерволе, то /var/log/auth.log будет фиксировать только те сессии, которые вы инициировали сами.
Цена этого решения заключается в том, что tor находится на пути каждой сессии администратора. Это демон пользовательского пространства, который должен запуститься и инициализироваться после каждой перезагрузки, прежде чем вы сможете войти в систему. Учтите это перед тем, как закрыть порт, так как в случае сбоя вы рискуете потерять доступ к машине, к которой у вас нет физического доступа.
Обеспечьте доступ для восстановления перед началом работ
Не приступайте к работе, пока у вас нет пути восстановления, не зависящего от SSH.
Откройте консоль вашего провайдера — VNC или последовательную консоль в панели управления — и войдите в систему. Если пароль root неизвестен, сначала сбросьте пароль root через панель управления и убедитесь, что он работает. Консоль, которую вы никогда не проверяли, не является надежным путем восстановления.
Порядок действий ниже имеет значение. Каждый шаг проверяется перед выполнением следующего, а порт 22 остается открытым до тех пор, пока не заработает onion-маршрут.
- Установите tor и убедитесь, что он успешно проходит bootstrap.
- Настройте onion-сервис и получите его адрес.
- Подключитесь через onion-адрес, пока порт 22 все еще открыт.
- Добавьте клиентскую авторизацию и подключитесь снова.
- Привяжите
sshdк loopback-интерфейсу и закройте порт 22. - Перезагрузитесь, затем снова подключитесь через onion-адрес.
Держите текущую SSH-сессию открытой на протяжении всего процесса. Установленная сессия сохраняется при изменении правил файрвола, которые заблокировали бы новое подключение, поэтому она является вашим первым средством спасения.
Установка Tor на сервер
В репозиториях Ubuntu поставляется версия Tor, которая часто отстает от актуальной. В репозитории The Tor Project содержится версия, описанная в их документации. Добавьте его, используя команды из их руководства по 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Выполните /etc/apt/sources.list.d/tor.sources. Suites использует кодовое имя вашего дистрибутива, которое выводит lsb_release -cs (noble в 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-pagerЛог должен заканчиваться строкой Bootstrapped 100% (done). Если процесс завис на этом этапе, значит, Tor не может получить доступ к сети. Почти всегда причина кроется в исходящих правилах межсетевого экрана или неверно настроенных системных часах.
Имя юнита — это ловушка. systemctl status tor сообщает Active: active (exited) даже при полной исправности системы, так как в Debian и Ubuntu пакет Tor реализован как мастер-юнит для нескольких экземпляров, чья единственная задача — запуск основного процесса. Сам демон работает как tor@default.service. Используйте это имя для status и journalctl. Команды start, stop и reload для tor по-прежнему передаются экземпляру, поэтому sudo systemctl reload tor работает так, как вы ожидаете.
Настройка onion-сервиса для порта 22
Добавьте две строки в /etc/tor/torrc.
HiddenServiceDir /var/lib/tor/ssh/
HiddenServicePort 22 127.0.0.1:22Вторая строка указывает tor принимать соединения на виртуальный порт 22 по onion-адресу и перенаправлять их на 127.0.0.1:22 на данном сервере. Tor обращается к sshd через loopback, именно поэтому впоследствии можно отключить прослушивание sshd на публичном IP-адресе.
sudo systemctl reload tor
sudo cat /var/lib/tor/ssh/hostnameЭта команда выведет 56 символов в кодировке base32, за которыми следует .onion. Эти символы представляют собой публичный ключ сервиса в закодированном виде. В этой схеме отсутствуют центры сертификации и регистрация имен.
Позвольте tor самостоятельно создать /var/lib/tor/ssh/. Если создать директорию вручную с неверным владельцем или правами доступа менее строгими, чем 0700, tor откажется её использовать, а в журнале появится сообщение о слишком широких правах доступа к директории. Файлы внутри определяют идентификатор сервиса: hs_ed25519_secret_key и есть адрес. Создайте резервную копию этой директории с правами 600 и храните её вне сервера, так как её потеря приведет к смене адреса и необходимости обновлять конфигурацию на всех клиентах.
Подключение с рабочей станции
На вашей рабочей станции должен быть установлен Tor-клиент, который не требует никакой настройки. В Debian или Ubuntu это sudo apt install -y tor netcat-openbsd. После запуска Tor ожидает соединений на 127.0.0.1:9050 в качестве SOCKS5-прокси. SOCKS — это универсальный протокол проксирования, а его 5-я версия поддерживает передачу имени хоста вместо IP-адреса, что является ключевым моментом в данном случае.
У OpenSSH нет собственного SOCKS-клиента, поэтому для установки соединения используется вспомогательная программа. Добавьте следующие строки в ~/.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 выбирает SOCKS5, а -x 127.0.0.1:9050 указывает на локальный Tor. %h передает onion-адрес в Tor как имя хоста, чтобы Tor разрешил его внутри своей сети. Для этого необходимо использовать OpenBSD netcat. У GNU netcat нет опции -X, и он завершит работу с ошибкой nc: invalid option -- 'X'.
ssh myvpsПервое соединение будет медленным, так как Tor сначала должен построить цепочку узлов. Примите отпечаток ключа хоста так же, как вы делаете это в любом другом случае. Далее применяются стандартные правила работы с SSH-ключами без изменений. Транспортный уровень изменился, но механизм аутентификации остался прежним.
Для разового подключения можно обойтись без записи в конфигурационном файле: команда torsocks ssh admin@xxxxx.onion выполняет ту же задачу.
Добавление авторизации клиента v3
В текущем состоянии любой, кто узнает адрес, может увидеть ваш SSH-баннер и начать подбор пароля. Onion-адреса невозможно перечислить через систему каталогов, поэтому адрес работает как секрет, но он может утечь обычными путями: через историю командной оболочки или конфигурационные файлы, закоммиченные в git-репозиторий. Авторизация клиента закрывает эту брешь. Сервис публикует свой дескриптор, зашифрованный ключом клиента, поэтому тот, у кого есть адрес, но нет ключа, даже не сможет обнаружить сервис.
Создайте пару ключей x25519 на клиенте. Это конвейер команд из руководства по авторизации клиента от Tor Project с одним изменением.
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Опубликованная версия этих строк использует base64pem -d, которого нет в стандартной установке Ubuntu. В результате команда завершается с ошибкой base64pem: command not found. GNU base64 -d декодирует то же самое тело PEM, поэтому используйте его.
На сервере установите открытый ключ.
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Считываются только файлы, заканчивающиеся на .auth. Если сохранить файл как laptop.auth.txt, tor проигнорирует его без вывода ошибки, и сервис останется открытым для любого, кто знает адрес.
На клиенте установите закрытый ключ. В Ubuntu демон tor работает от имени пользователя debian-tor и не может читать файлы в вашей домашней директории, поэтому разместите директорию там, где этот пользователь имеет права доступа.
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Добавьте ClientOnionAuthDir /var/lib/tor/onion_auth в файл /etc/tor/torrc на клиенте и перезагрузите tor. Если вы запускаете tor от своего имени, например, при использовании сборки Homebrew в macOS, укажите ClientOnionAuthDir путь к ~/.tor/onion_auth с правами 0700.
Адрес внутри этого файла — это 56 символов без суффикса .onion. Удалите /tmp/k1.prv.pem и /tmp/k1.prv.key после завершения работы.
Теперь проверьте оба направления. ssh myvps должен по-прежнему подключаться. С машины, на которой нет ключа, попытка подключения к тому же адресу должна завершиться неудачей. Этот отказ — доказательство того, что авторизация активна.
Закрытие порта 22 в указанном порядке
Сначала создайте «страховочную сеть». Эта команда отменит оба изменения, описанные ниже, через 15 минут, если вы потеряете доступ к серверу.
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'Отмените её командой sudo systemctl stop ssh-rescue.timer, как только убедитесь, что маршрут через Tor продолжает работать.
Затем остановите прослушивание sshd на публичном адресе. В Ubuntu 24.04 SSH активируется через socket-юнит, поэтому параметр ListenAddress в файле sshd_config игнорируется: ssh.socket управляет прослушивающим сокетом, а не sshd. Проверьте, какой случай относится к вашей системе.
systemctl is-enabled ssh.socketЕсли команда выведет enabled, выполните sudo systemctl edit ssh.socket и добавьте следующее содержимое.
[Socket]
ListenStream=
ListenStream=127.0.0.1:22Пустое значение ListenStream= очищает значение, унаследованное от штатного юнита. Если пропустить эту строку, вы добавите второй слушающий сокет, сохранив при этом публичный — это самая частая причина, по которой данный шаг не приносит результата, хотя ошибок не возникает.
sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
ss -tlnp | grep ':22'Команда ss должна показать 127.0.0.1:22 и отсутствие записей на 0.0.0.0:22. Если ssh.socket был отключен, добавьте ListenAddress 127.0.0.1 в /etc/ssh/sshd_config.d/10-onion.conf, выполните sudo systemctl restart ssh, а затем проверьте результат той же строкой ss. Этот вывод является подтверждением в обоих случаях.
Далее настройте межсетевой экран, используя стандартные правила ufw на VPS. Сначала выполните sudo ufw status numbered и удалите все правила SSH, которые будут выведены в списке.
sudo ufw status numbered
sudo ufw delete allow OpenSSH
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw status verboseОставьте исходящий трафик разрешенным. Tor подключается к релеям через порты, такие как 443 и 9001, поэтому политика default-deny для исходящего трафика остановит процесс загрузки Tor и одновременно лишит вас последнего способа подключения к серверу. Большинство провайдеров также используют отдельный сетевой экран в панели управления. Закройте порт 22 и там, иначе он останется доступным независимо от того, что показывает ufw.
Если на сервере запущен Docker, проверьте опубликованные порты, прежде чем считать задачу выполненной. Docker записывает свои правила непосредственно в таблицы iptables и публикует порты контейнеров в обход ufw, поэтому политика запрета в ufw не дает полной картины безопасности.
Перезагрузка перед проверкой
systemctl is-enabled tor@default
sudo rebootЕсли первая команда не показывает, что сервис включен, выполните sudo systemctl enable tor@default перед перезагрузкой. Подождите две минуты, затем выполните ssh myvps. Tor должен пройти процедуру bootstrap после загрузки, поэтому onion-адрес начинает отвечать через некоторое время после запуска самой машины.
Если сервис не восстанавливает работу, откройте консоль и прочитайте sudo journalctl -u tor@default -b. Там будет указана синтаксическая ошибка в torrc или проблема с правами доступа к директории. Вы также можете проверить правки в файле torrc перед их применением.
sudo -u debian-tor tor --verify-configСравнение стоимости с туннелем WireGuard
По сравнению с собственным VPN на базе WireGuard на VPS, onion-сервис работает медленнее и менее предсказуемо. Будьте честны с собой относительно этого компромисса, прежде чем принимать решение.
Задержка. Клиентская цепочка состоит из трех ретрансляторов, а сторона сервиса добавляет еще три, поэтому ваши нажатия клавиш проходят примерно через шесть случайных машин по всему миру. Интерактивный ввод имеет заметную задержку, а копирование файлов происходит медленно. WireGuard добавляет только один узел. Измерьте показатели для вашего случая с помощью time ssh myvps 'echo ok', так как значение зависит от того, какую цепочку построил Tor, и оно меняется при построении новой цепочки.
Демон в пространстве пользователя на критическом пути. WireGuard работает на уровне ядра и поднимается вместе с сетью. Tor — это процесс, который должен запуститься, выполнить начальную загрузку и достичь guard-ретранслятора, прежде чем что-либо заработает. Если он не запускается, вам придется использовать консоль провайдера.
Точность системного времени. Дескрипторы onion-сервисов публикуются с привязкой к временным интервалам, поэтому значительное расхождение часов нарушает поиск адреса без каких-либо явных сообщений об ошибках. timedatectl должен возвращать System clock synchronized: yes.
Взамен вы получаете уровень защиты, который больше не зависит от корректности правил межсетевого экрана. Здесь нет портов для сканирования и баннеров для захвата, а сам адрес является открытым ключом, поэтому конечная точка подтверждает свою подлинность еще до начала сессии SSH.
На практике обычно используют оба варианта. Запускайте WireGuard для повседневной работы, а onion-сервис оставьте как резервный путь, который продолжит работать, если конфигурация WireGuard окажется неверной. Это позволяет оставить открытым один UDP-порт вместо публичного SSH-порта. Ничто из этого не заменяет укрепление безопасности самого sshd: аутентификация только по ключам и вход не под root по-прежнему важны, так как onion-сервис защищает только сетевой путь, но не то, что находится за ним.
Режимы сбоев и возникающие ошибки
Tor никогда не проходит Bootstrapped 0%. Исходящий трафик заблокирован или системные часы сильно отстают. Проверьте политику исходящих соединений с помощью sudo ufw status verbose, затем выполните timedatectl.
systemctl status tor сообщает active (exited). Это нормальное поведение для Debian и Ubuntu. Вместо этого читайте tor@default.
Дескриптор не найден. Tor возвращает расширенную ошибку SOCKS F0: "Onion Service Descriptor Can Not be Found". Либо дескриптор еще не опубликован (это занимает некоторое время после перезагрузки), либо процесс tor на сервере не запущен.
F4, "Onion Service Missing Client Authorization". У клиента нет подходящего .auth_private, который может использовать tor. Убедитесь, что ClientOnionAuthDir указан в torrc, права доступа к директории установлены в 0700, имя файла заканчивается на .auth_private, и что debian-tor имеет права на чтение этого файла.
F5, "Onion Service Wrong Client Authorization". Закрытый ключ не соответствует файлу .auth на сервере. Причиной может быть лишний = или случайный символ переноса строки внутри base32-строки.
nc: invalid option -- 'X'. Установлен GNU netcat вместо версии OpenBSD. Выполните sudo apt install -y netcat-openbsd.
Could not resolve hostname. ssh попытался использовать обычный DNS, который не содержит ответа для .onion, поэтому ProxyCommand не был запущен. Шаблон Host в ~/.ssh/config не соответствует введенному вами имени.
Permission denied (publickey). Туннель сработал, и работа tor завершена. Рассматривайте это как обычную проблему отказа в доступе по ключу (permission denied publickey) и не учитывайте tor в данном случае.
FAQ
Означает ли использование onion-сервиса, что на моем VPS нет открытых портов?
Да, если sshd привязан к 127.0.0.1, а межсетевой экран блокирует входящий трафик. Tor устанавливает исходящее TCP-соединение с реле, и ваша сессия проходит через него в обратном направлении, поэтому ни один процесс на сервере не принимает соединения по публичному адресу. Проверьте это с помощью ss -tlnp на сервере и сканированием портов извне. Не забудьте про сетевой экран провайдера в панели управления: это отдельный уровень защиты, независимый от ufw, его также необходимо закрыть.
Достаточно ли одного .onion-адреса для безопасности SSH?
Нет. Адрес состоит из 56 символов, его невозможно угадать или перебрать через систему каталогов, поэтому он работает как секретный ключ, но он может утечь через историю командной оболочки или файлы конфигурации. Добавьте авторизацию клиента v3. В этом случае дескриптор сервиса шифруется вашим клиентским ключом, поэтому любой, у кого есть только адрес, получит расширенную ошибку F4 и даже не дойдет до sshd.
Что произойдет, если tor не запустится после перезагрузки?
Вы полностью потеряете доступ по SSH, так как onion-адрес будет единственным способом входа. Именно поэтому необходимо протестировать консоль провайдера до того, как вы закроете порт 22. Tor также требуется время на инициализацию после загрузки, поэтому адрес начинает отвечать позже, чем машина начинает отвечать на ping. Если ответа нет, войдите через консоль и прочитайте sudo journalctl -u tor@default -b: там будет указана синтаксическая ошибка в torrc или проблема с правами доступа к /var/lib/tor/ssh.
Является ли SSH поверх Tor медленнее, чем WireGuard?
Да, значительно. Соединение с onion-сервисом проходит через шесть случайно выбранных реле, тогда как WireGuard — это один зашифрованный переход напрямую к вашему серверу. Ввод текста ощущается с задержкой, а передача данных происходит медленно. Распространенная схема — использование WireGuard для повседневной работы, при этом onion-сервис остается резервным каналом на случай сбоя конфигурации VPN.