SSH через Tor

Продовжую тему про SSH. Сьогодні буде дещо дійсно магічне: як (і навіщо!) використовувати SSH через Tor Hidden Service.

Цей пост написаний для тих, хто знає що таке The Onion Router хоча б на рівні статті у Вікіпедії.

Багато хто використовує Tor для доступу до заблокованих сайтів. Також багато хто користується Tor, щоб уникнути стеження. Та про «приховані сервіси» Tor чули не всі; й навіть хто чув, часто сприймають це лише як «сайти в даркнеті». Але це дещо більше. Зокрема, для мене це метод обходу NAT.

Так, щоб запустити сервер з прихованими сервісами Tor, вам не потрібна «біла» IP-адреса, що маршрутизується. Все, що треба для запуску прихованого сервісу, це працюючий сервіс Tor і хоч якесь підключення до інтернету. Ваш Tor автоматично з’єднається з іншими вузлами мережі Tor, після чого зможе опрацьовувати вхідні з’єднання.

Піти по SSH на хост за NATом завжди складно. Є багато методів вирішення цієї проблеми: або ProxyJump через проміжний хост, або port forwarding на роутері, або через VPN, або ще якось.

Тож, знати про додатковий метод доступу ніколи не завадить.

Але одразу попереджаю: через Tor все робиться досить повільно. На мою думку, доступ через Tor найкраще підходить у якості запасного, «аварійного» методу доступу. Також нормально підходить для якихось неінтерактивних скриптів, для яких час виконання не є критичним.

Налаштування Tor

Нехай у нас є два хоста, умовно «клієнт» та «сервер». (Насправді, щоб поекспериментувати, можна все це зробити на одному локальному хості).

Треба встановити Tor як на клієнті, так і на сервері:

apt-get install tor

Клієнтський Tor не потребує додаткових налаштувань, а от у серверному доведеться дещо зробити. Відкрийте /etc/tor/torrc та допишіть десь там в кінці такі рядки:

HiddenServiceDir /var/lib/tor/my-ssh
HiddenServiceVersion 3
HiddenServicePort 22 127.0.0.1:22

Перезапустіть Tor (service tor restart). Після цього має з’явитися каталог /var/lib/tor/my-ssh, де Tor тримає приватні ключі і всякі інші штуки. Зокрема, там буде файл з назвою hostname. Це і є щойно згенероване ім’я вашого нового прихованого сервісу Tor.

Про версію протоколу

  • Адреси з протоколу версії 2 виглядають як xxxxxxxxxxxxxxxx.onion
  • Протокол версії 3 це xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.onion
  • Оголошення про зміну версії протоколу

Рядок з HiddenServiceVersion потрібен лише для дуже старих версій Tor. Наприклад, у Ubuntu 18.04 LTS використовується збірка Tor 0.3.2.10-1, яка за замовчанням використовує протокол застарілої версії 2, хоча також вміє протокол версії 3. Ну, що поробиш, це LTS.

А мій Debian GNU/Linux Sid (unstable) має свіжу збірку 0.4.7.8-1, з якої вже півроку як остаточно випиляли будь-які згадки про протокол версії 2, бо він визнаний ненадійним.

Налаштування SSH

Тепер нам треба налаштувати SSH на клієнті.

Сервіс Tor за замовчанням доступний як SOCKSv5 проксі на локальному порту 9050. Нам треба переспрямувати SSH через цей проксі, і зробити це можна через NetCat.

Тож, пишемо у наш .ssh/config щось отакого виду:

Host tor-host1
  HostName xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.onion
  HostKeyAlias host1
  VerifyHostKeyDNS no
  ProxyCommand nc -x localhost:9050 -X 5 %h %p

Очевидно, що тут замість host1 вказуєте якесь нормальне ім’я, а замість xxxx пишете оту адресу, яку згенерував сервіс Tor на сервері.

Запускаємо ssh tor-host1 та… неприємно дивуємося, як довго треба чекати :(

У мене з’єднання через Tor триває 15–20 секунд. Після з’єднання все дуже повільне, немов я повернувся у дев’яності і знову користуюся модемом на 2400. Консольні програми через Tor здебільшого юзабельні, але не дуже зручні.

Так чи інакше, на цьому етапі у вас є працюючий доступ по SSH через прихований сервіс Tor. Сервер може переїхати, може змінити IP-адресу, або до нього може значно змінитися маршрутизація, але він все одно буде доступним. Це ж круто!

Більше магії

Досить типово, що у мене є кілька визначень різних методів доступу до одного і того ж хоста: крім доступу через Tor, є і «звичайні» методи доступу. Тобто десь є визначення доступу до хоста host1 (яке може працювати, наприклад, лише в певній локальній мережі), а окремо від нього є визначення tor-host1 (яке має працювати будь-де).

Уявімо, що у хоста host1 IP-адреса 10.20.30.40 в нашій локальній мережі, і що sshd на ньому слухає порт 2250. Тож конфігурація буде така:

Host host1
  HostName 10.20.30.40
  Port 2250
  HostKeyAlias host1

Host tor-host1
  HostName xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.onion
  HostKeyAlias host1
  VerifyHostKeyDNS no
  ProxyCommand nc -x localhost:9050 -X 5 %h %p

В принципі, тут все нормально. Та чи можна зробити ще зручніше?

SSH має механізм умовних визначень. Можна написати команду або скрипт, які будуть перевіряти певну умову, і через це впливати на стан конфігурації. Дехто пише для цього складні скрипти. Тут буде відносно простий приклад умовної конфігурації.

За допомогою все того ж NetCat (а саме nc -z) ми можемо перевірити умову, що хтось з вказаною адресою слухає на вказаному порту. З цього можна зробити припущення, що ми знаходимося у деякій відомій нам мережі.

Тож, дивіться.

Match Host host1 exec "nc -w1 -z 10.20.30.40 2250"
  HostName 10.20.30.40
  Port 2250
  HostKeyAlias host1

Host host1 tor-host1
  HostName xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.onion
  HostKeyAlias host1

Host tor-host2
  HostName xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.onion
  HostKeyAlias host2

CanonicalizeHostname yes
Host *.onion
  VerifyHostKeyDNS no
  ProxyCommand nc -x localhost:9050 -X 5 %h %p

Що тут відбувається?

  • Команди ssh tor-host1 та ssh tor-host2 завжди (безумовно) йтимуть через Tor
  • Команда ssh host1 перевірить (з обмеженням часу на перевірку в 1 секунду), чи доступний 10.20.30.40:2250 і якщо це дійсно так, то SSH спробує з’єднатися напряму, а якщо ні, то з’єднання піде через Tor

Магія.

Тред у Твітері.