Настройка SSH через Tor onion service без открытых портов
Узнайте, как скрыть SSH-сервер за Tor onion service для защиты от сканеров. Инструкция по настройке v3 авторизации и последовательность действий, исключающая потерю доступа.
Что меняет использование SSH через Tor onion service
SSH через Tor onion service позволяет администрировать VPS, которая не принимает входящие соединения ни на один порт. Сервер устанавливает исходящее соединение с сетью Tor и поддерживает его в открытом состоянии. Ваша SSH-сессия проходит через этот канал, поэтому на публичном IP-адресе не требуется открывать порты для прослушивания.
Влияние на логи заметно сразу. Сервер с открытым публичным SSH-портом ежедневно собирает тысячи попыток подбора пароля от сканеров. Перенесите sshd за onion service и заблокируйте входящий трафик на фаерволе, и тогда /var/log/auth.log будет фиксировать только те сессии, которые инициировали вы.
Цена этого решения заключается в том, что tor находится на пути каждой сессии администратора. Это демон пользовательского пространства, который должен запуститься и инициализироваться после каждой перезагрузки, прежде чем вы сможете войти в систему. Учтите это перед тем, как закрыть порт, так как в случае сбоя вы рискуете потерять доступ к машине, к которой у вас нет физического доступа.
Обеспечьте путь для восстановления перед началом работ
Не приступайте к работе, пока у вас нет способа восстановления, не использующего SSH.
Откройте консоль вашего провайдера — VNC или последовательную консоль в панели управления — и войдите в систему через неё. Если пароль root неизвестен, сначала сбросьте пароль root через панель управления и убедитесь, что он работает. Консоль, которую вы никогда не проверяли, не является надежным путем восстановления.
Порядок действий ниже имеет значение. Каждый шаг проверяется перед выполнением следующего, а порт 22 остается открытым до тех пор, пока не заработает onion-маршрут.
- Установите tor и убедитесь, что он успешно проходит bootstrap.
- Настройте onion service и получите его адрес.
- Подключитесь через 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 не может получить доступ к сети. Почти всегда причина кроется в исходящих правилах firewall или неверно настроенном системном времени.
Имя юнита — это ловушка. 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-адресе. Если указать во второй строке веб-сервер на 127.0.0.1:80, эти же две директивы позволят опубликовать сайт на onion-адресе, что является полезным вторым сервисом после установки tor.
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, как только убедитесь, что onion-маршрут по-прежнему работает.
Затем остановите прослушивание 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 записывает свои правила в те же таблицы и публикует порты контейнеров в обход ufw, поэтому политика deny в 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 — это процесс, который должен запуститься, пройти процедуру bootstrap и установить соединение с guard-ретранслятором, прежде чем что-либо заработает. Если он не запускается, вам придется использовать консоль провайдера.
Точность системного времени. Дескрипторы onion-сервисов публикуются с привязкой к временным интервалам, поэтому значительное расхождение часов нарушает поиск адреса без каких-либо явных сообщений об ошибках. timedatectl должен возвращать System clock synchronized: yes.
Взамен вы получаете уровень защиты, который больше не зависит от корректности правил межсетевого экрана. Здесь нет порта для сканирования и баннера для захвата, а сам адрес является открытым ключом, поэтому конечная точка подтверждает свою подлинность еще до начала сессии SSH.
На практике обычно используют оба варианта. Запускайте WireGuard для повседневного доступа и держите onion-сервис как резервный маршрут, который продолжит работать, если конфигурация WireGuard окажется неверной. Это оставляет открытым один UDP-порт вместо публичного SSH-порта. Ничто из этого не отменяет необходимости укрепления безопасности самого sshd: аутентификация только по ключам и вход под непривилегированным пользователем по-прежнему важны, так как 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.