Tunkit: Конструктор SSH-туннелей

👉Страница проекта на GitHub

Домашнаяя страница данного проекта находится на GitHub: dadooda/tunkit. Все ссылки ведут туда же.

Введение

Туннелирование SSH (переадресация портов) — это метод передачи произвольных данных по зашифрованному соединению SSH. Туннель SSH перенаправляет ваш трафик через удаленный сервер, такой как VPS или выделенный сервер. Весь ваш трафик, «проксируемый» через туннель, похоже, поступает с удаленного сервера, а не с вашей локальной машины. Эти функции туннелей SSH используются для шифрования трафика устаревших приложений, реализации VPN (виртуальных частных сетей), доступа к локальным (внутрисетевым) службам через брандмауэры и т. д.

Большинство известных реализаций SSH для различных платформ прекрасно справляются с созданием одноразовых туннелей. Интернет буквально забит рецептами типа «создать SOCKS-прокси на основе SSH за 5 минут, чтобы обойти ограничения брандмауэра» или «создать SSH-туннель для удаленного рабочего стола». Однако ни в одной из таких «удобных» статей не объясняется, как контролировать и управлять такими туннелями, как сделать их надежными и безопасными.

Tunkit возник как набор скриптов autossh, чтобы помочь запустить и остановить несколько простых туннелей при загрузке машины. Постепенно добавлялись сценарии, а вместе с ними и возможности. Снова и снова настраивая различные туннели в разных средах, я продолжал делать решение более гибким, но в то же время более простым и надежным.

В результате вы получаете то, что видите — «сборочный комплект», позволяющий за считанные минуты создать туннельную установку производственного уровня практически для любой задачи, руководствуясь точными пошаговыми инструкциями из этого README.

🔝

Сделано на Procdown

Этот файл README был составлен с использованием Procdown, инструмента для написания и поддержки многостраничных документов Markdown со структурой и множеством внутренних ссылок.

🔝

Поехали!

Эти основные шаги необходимо выполнить для любого из перечисленных ниже сценариев:

  1. Выполните шаги “Настройка сервера: SSH”.
  2. Выполните шаги “Настройка сервера: Пользователь и ключ”.
  3. Выполните шаги “Настройка клиента”: 🎲Linux или WSL, 🎲Cygwin.

Ниже — несколько типовых пошаговых сценариев.

Настройка SOCKS-прокси для обхода блокировок

  1. Выполните основные шаги.
  2. Настройте SOCKS-туннель.
  3. Настройте автозапуск службы: 🎲Linux, 🎲WSL, 🎲Cygwin.

🔝

Настройка прямого SSH-доступа к Linux-серверу, работающему на виртуальной машине или в облаке

  1. Выполните основные шаги.
  2. Настройте туннель удаленного доступа.
  3. При необходимости настройте автозапуск службы.
  4. При необходимости настройте монитор по требованию.

🔝

Настройка удалённого доступа к моей Windows-машине через RDP или VNC

  1. Выполните основные шаги.
  2. Настройте туннель удаленного доступа.
  3. При необходимости настройте автозапуск службы.
  4. При необходимости настройте монитор по требованию.

🔝

Настройка домашнего сервера или NAS для создания нескольких туннелей к машинам в моей локальной сети

  1. Выполните основные шаги.
  2. На сервере настройте несколько туннелей удаленного доступа (🎲Linux, 🎲WSL) к другим машинам/сервисам в локальной сети.
  3. Настройте многоканальный монитор по запросу.
  4. По желанию настроить автозапуск службы: 🎲Linux, 🎲WSL.

🔝

Пошаговая настройка

Настройка сервера: SSH

📝 Требования:

  1. Сервер шлюза, ec2-13-34-43-202.compute-1.amazonaws.com, работает под управлением довольно свежего популярного дистрибутива Linux, такого как Ubuntu.
  2. Сервер SSH, работающий по адресу ec2-13-34-43-202.compute-1.amazonaws.com, настроен в соответствии с актуальными значениями по умолчанию.
  3. Пользователь joe может sudo изменять системные настройки Linux.

С помощью SSH войдите на сервер шлюза, ec2-13-34-43-202.compute-1.amazonaws.com:

ssh joe@ec2-13-34-43-202.compute-1.amazonaws.com

💡 На данный момент все команды выполняются на сервере шлюза, ec2-13-34-43-202.compute-1.amazonaws.com.

Отредактируйте конфигурацию SSH-сервера:

sudoedit /etc/ssh/sshd_config

Укажите параметр GatewayPorts:

GatewayPorts clientspecified

Активировать изменения конфигурации:

sudo service ssh reload

Наш SSH-сервер должен быть готов к работе.

🔝

Настройка сервера: Пользователь и ключ

С помощью SSH войдите на сервер шлюза, ec2-13-34-43-202.compute-1.amazonaws.com:

ssh joe@ec2-13-34-43-202.compute-1.amazonaws.com

💡 На данный момент все команды выполняются на сервере шлюза, ec2-13-34-43-202.compute-1.amazonaws.com.

Добавьте неинтерактивного пользователя joetun:

sudo adduser --disabled-password --shell /usr/sbin/nologin --gecos "Joe's tunnel" joetun
Adding user `joetun' ...
Adding new group `joetun' (1001) ...
Adding new user `joetun' (1001) with group `joetun' ...
Creating home directory `/home/joetun' ...
Copying files from `/etc/skel' ...

Давайте посмотрим, что у нас есть до сих пор:

grep joetun /etc/passwd
joetun❌1001:1001:Joe's tunnel,,,:/home/joetun:/usr/sbin/nologin

Выглядит неплохо. Теперь приступим к генерации ключей:

mkdir -p /tmp/joetun-key &&
cd /tmp/joetun-key &&
ssh-keygen -t ed25519 -b 512 -N "" -C "Joe's tunnel" -f joetun.key
Generating public/private ed25519 key pair.
Your identification has been saved in joetun.key
Your public key has been saved in joetun.key.pub
…

💡 Мы выбрали ed25519 в качестве типа ключа. Для получения дополнительной информации о выборе типа ключа пожалуйста, обратитесь к Comparing SSH Keys - RSA, DSA, ECDSA, or EdDSA? или аналогичным статьям.

⚠️ У сгенерированного закрытого ключа joetun.key нет парольной фразы. Убедитесь, что вы не используете этот ключ ни для чего, кроме туннелей.

Теперь скопируйте оба joetun.key и joetun.key.pub с удаленного сервера в безопасное место.

  • Если вы используете Linux, используйте scp, например:

    mkdir -p ~/saved-keys &&
    scp joe@ec2-13-34-43-202.compute-1.amazonaws.com:/tmp/joetun-key/joetun.key* ~/saved-keys
    
  • Если вы работаете в Windows и у вас установлено PuTTY, используйте pscp, например:

    mkdir %USERPROFILE%\saved-keys
    pscp joe@ec2-13-34-43-202.compute-1.amazonaws.com:/tmp/joetun-key/joetun.key* %USERPROFILE%\saved-keys
    
  • Если ничего из вышеперечисленного не работает для вас, вы всегда можете по умолчанию сохранить фактическое содержимое файла. Поскольку ключевые файлы созданы для копирования и вставки, просто соберите и сохраните точный вывод команды cat.

    cat joetun.key.pub joetun.key
    
    ssh-ed25519 AAAAC3Nzxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxov2DWA0z Joe's tunnel
    -----BEGIN OPENSSH PRIVATE KEY-----
    b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    DqXqkQQZ9af0ov2DWA0zAAAADEpvZSdzIHR1bm5lbAE=
    -----END OPENSSH PRIVATE KEY-----
    

Теперь давайте настроим нашего вновь созданного пользователя joetun на использование авторизации по ключу SSH. Находясь в /tmp/joetun-key, выполните следующие команды:

sudo runuser -u joetun bash
cd &&
touch .hushlogin &&
mkdir -pm 700 .ssh &&
touch .ssh/authorized_keys &&
chmod 600 .ssh/authorized_keys &&
cat /tmp/joetun-key/joetun.key.pub >> .ssh/authorized_keys &&
exit

💡 Как вы могли догадаться, в приведенной выше последовательности команд мы стали пользователем joetun (через runuser), сделал пару вещей от его имени и вернулся в нашу обычную оболочку после exit.

Теперь давайте проверим, работает ли авторизация по ключу для joetun. Находясь в /tmp/joetun-key, выполните:

ssh -i joetun.key joetun@localhost
The authenticity of host 'localhost (::1)' can't be established.
ECDSA key fingerprint is SHA256:4fyuZVMRxxxxxxxxxxxxxxxxxxxxxxxxxxxAJ6KR3bQ.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

Введите yes и нажмите ENTER. Затем вы должны увидеть:

This account is currently not available.
Connection to localhost closed.

Ура. Наш пользователь туннеля, joetun готов к работе, и у нас есть как закрытый, так и открытый ключи. скопировано в безопасное место.

Приступаем к очистке:

cd &&
rm -rf /tmp/joetun-key

🔝

Настройка сервера: Веб-сайт семафора на базе Nginx

📝 Требования:

  1. Вы можете создать A или CNAME записей DNS в существующем домене. В этом примере домен joescompany.com.
  2. У вас есть сервер в Интернете, работающий под управлением современного Linux, такого как Ubuntu, способного запускать программное обеспечение веб-сервера.
  3. Пользователь joe может sudo изменять системные настройки Linux на веб-сервере.

Создание веб-сайта семафора требуется для сценариев по запросу, таких как “Настройка туннеля: Удалённый доступ по требованию (Linux или WSL)” и “Настройка туннеля: Многоканальный удалённый доступ по требованию (Linux или WSL)”.

При настройке веб-сайта семафора учитывайте следующее:

  1. Сайт должен быть HTTPS. Сегодня многие интернет-провайдеры перехватывают ответы HTTP 404 и показывают свою рекламу, принудительно переписывая статус HTTP на 200.
  2. URL-адреса семафора должны отвечать статусом HTTP 200, если семафор работает, и 404, если он не работает.
  3. Из соображений надежности желательно, чтобы веб-сайт семафора находился отдельно от любых существующих сайтов, в его собственном домене с собственным сертификатом SSL.

В панели управления DNS joescompany.com создайте запись secret типа A или CNAME, указывающую на хост веб-сервера. Например:

secret IN A 45.56.76.21

Подождите несколько минут, пока изменения вступят в силу. Обычно это занимает от 10–15 минут до часа.

Давайте проверим нашу новую запись DNS:

ping secret.joescompany.com
PING li926-21.members.linode.com (45.56.76.21) 56(84) bytes of data.
64 bytes from li926-21.members.linode.com (45.56.76.21): icmp_seq=1 ttl=42 time=105 ms
64 bytes from li926-21.members.linode.com (45.56.76.21): icmp_seq=2 ttl=42 time=105 ms
…

👍 Отлично, DNS-имя secret.joescompany.com отвечает.

Теперь давайте настроим простой статический сайт на Nginx.

ssh joe@secret.joescompany.com

💡 На данный момент все команды выполняются на веб-сервере, secret.joescompany.com.

Установите автоматический генератор сертификатов SSL, Certbot.

💡 Вы можете использовать любого другого провайдера SSL и программное обеспечение. В этом примере предполагается, что вы используете Certbot.

Установите веб-сервер Nginx:

sudo apt install nginx

Создайте новую конфигурацию веб-сайта Nginx:

sudoedit /etc/nginx/sites-available/secret.joescompany.com
server {
  listen 443 ssl;
  server_name secret.joescompany.com;

  ssl_certificate /etc/letsencrypt/live/secret.joescompany.com/cert.pem;
  ssl_certificate_key /etc/letsencrypt/live/secret.joescompany.com/privkey.pem;

  access_log /var/log/nginx/secret.joescompany.com_access.log;
  error_log /var/log/nginx/secret.joescompany.com_error.log;

  location / {
    root /home/joe/www/secret.joescompany.com/html;
    index index.html;
  }
}

Включить наш сайт:

cd /etc/nginx/sites-enabled &&
sudo ln -s ../sites-available/secret.joescompany.com

С помощью Certbot сгенерируйте сертификат для secret.joescompany.com:

sudo certbot certonly --nginx

💡 В этом коротком примере мы не рассматриваем детали создания и настройки SSL-сертификата. Пожалуйста, обратитесь к соответствующим страницам Certbot.

Перезапустите Nginx:

sudo service nginx reload

Создайте манекен index.html:

mkdir -p ~/www/secret.joescompany.com/html &&
cd ~/www/secret.joescompany.com/html &&
echo "Go away" > index.html

Попробуй это:

curl -D - -k https://secret.joescompany.com
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: …
Content-Type: text/html
Content-Length: 17
Last-Modified: …
Connection: keep-alive
ETag: …
Accept-Ranges: bytes

Go away

Если вы видите это, то сайт семафора работает правильно.

🔝

Настройка клиента (Linux или WSL)

📝 Требования:

  1. Пользователь joe может sudo изменять системные настройки Linux.
  2. Вы успешно выполнили шаги “Настройка сервера: Пользователь и ключ”.

На локальном компьютере установите необходимые пакеты (названия Ubuntu):

sudo apt update &&
sudo apt install autossh curl git openssh-client

Получить Tunkit:

cd &&
git clone https://github.com/dadooda/tunkit.git &&
cd tunkit
Cloning into 'tunkit'...
remote: Enumerating objects: 510, done.
remote: Counting objects: 100% (145/145), done.
…
Resolving deltas: 100% (306/306), done.

Скопируйте ранее сохраненный закрытый ключ, joetun.key в Tunkit keys/:

cp -nt keys ~/saved-keys/joetun.key &&
chmod 600 keys/joetun.key

🔝

Настройка клиента (Cygwin)

Установите следующие пакеты:

  1. Из категории «Devel»: git.
  2. Из категории «Net»: autossh, curl, openssh.

Следуйте шагам «Настройка клиента (Linux или WSL)», начиная с «получить Tunkit».

🔝

Настройка туннеля: SOCKS (Linux, WSL или Cygwin)

📝 Требования:

  1. Вы успешно выполнили шаги “Настройка клиента”: 🎲Linux или WSL, 🎲Cygwin.

Войдите в каталог Tunkit:

cd ~/tunkit

Создайте конфиг для скрипта socks и отредактируйте его:

cp -n socks.d/conf.sh.example socks.d/conf.sh &&
${EDITOR} socks.d/conf.sh
C_HOST="ec2-13-34-43-202.compute-1.amazonaws.com"
C_USER="joetun"
C_KEY="joetun.key"
C_SOCKS_PORT="1080"

💡 Укажите ваше имя хоста шлюза в C_HOST= вместо ec2-13-34-43-202.compute-1.amazonaws.com.

Узнайте IP-адрес нашего хоста-шлюза, мы воспользуемся им через пару шагов:

ping ec2-13-34-43-202.compute-1.amazonaws.com
PING ec2-13-34-43-202.compute-1.amazonaws.com (13.34.43.202) 56(84) bytes of data.
64 bytes from ec2-13-34-43-202.compute-1.amazonaws.com (13.34.43.202): icmp_seq=1 ttl=41 time=45.6 ms
…

Запустите туннель, но в режиме отладки:

DEBUG=! ./socks
Running AutoSSH in the foreground
++ autossh -M 0 joetun@ec2-13-34-43-202.compute-1.amazonaws.com -D 0.0.0.0:1080 -i …
…
Authenticated to ec2-13-34-43-202.compute-1.amazonaws.com ([13.34.43.202]:22) using "publickey".
debug1: Local connections to 0.0.0.0:1080 forwarded to remote address socks:0
debug1: Local forwarding listening on 0.0.0.0 port 1080.
…

⚠️ Таких сообщений не должно быть:

bind [0.0.0.0]:1080: Address already in use
channel_setup_fwd_listener_tcpip: cannot listen to port: 1080
Could not request local forwarding.

Если есть такие сообщения, значит порт 1080 занят другим процессом. В этом случае остановите ./socks, нажав Ctrl+C, а затем либо найдите и остановите конкурирующий процесс, или настроить использование другого порта, например, C_PORT="8010". Затем снова запустите ./socks командой, указанной выше.

👍 Если все выглядит хорошо и нет явных сообщений об ошибках, то туннель работает.

Оставьте ./socks работающим там, где он есть, откройте новое окно терминала и двигайтесь дальше.

Запросите интернет-страницу, чтобы узнать наш внешний IP-адрес:

curl -s https://ipchicken.com | grep "^[0-9]*\..*<br>$"
172.58.44.119<br>

А теперь то же через туннель:

curl -x socks5://localhost:1080 -s https://ipchicken.com | grep "^[0-9]*\..*<br>$"
13.34.43.202<br>

Что мы видим? Внешний ресурс распознал наш трафик, исходящий от 13.34.43.202, который является IP-адресом нашего шлюза. Что, в свою очередь, означает, что наш туннель работает.

Вернитесь к исходному терминалу ./socks и остановите скрипт, нажав Ctrl+C.

Теперь давайте запустим туннель в фоновом режиме:

./socks-ctl start
Starting AutoSSH
AutoSSH is running, PID 11046

Проверьте еще раз с помощью команды curl -x socks5://…, написанной выше.

👍 Работает? Значит все хорошо. Что у нас в итоге получилось:

  1. Скрипт socks работает в фоновом режиме, запущенный с ./socks-ctl start.
  2. Локальный сервер SOCKS прослушивает localhost:1080. Любой интернет-клиент (например, веб-браузер) может отправлять свои данные через хост-шлюз, подключившись к локальному серверу SOCKS.

Далее, если вы хотите, чтобы туннель запускался автоматически при загрузке, выполните шаги “Настройка ОС: Автозапуск туннеля при загрузке”: 🎲Linux, 🎲WSL, 🎲Cygwin. 🔝

Настройка туннеля: Удалённый доступ (Linux)

💡 В этом примере сервер Linux работает на виртуальной машине. Если ваш сервер Linux размещен в облаке, действия точно такие же.

💡 В этом примере мы построим туннель к демону SSH, работающему внутри нашей Linux-машины. Чтобы построить туннель к другой службе, используйте другой номер локального порта вместо 22.

📝 Требования:

  1. Вы успешно выполнили шаги “Настройка клиента (Linux или WSL)”.

Войдите в каталог Tunkit:

cd ~/tunkit

Создайте конфиг для скрипта ra и отредактируйте его:

cp -n ra.d/conf.sh.example ra.d/conf.sh &&
${EDITOR} ra.d/conf.sh

Конфигурация, ra.d/conf.sh, выглядит так:

C_HOST="ec2-13-34-43-202.compute-1.amazonaws.com"
C_USER="joetun"
C_KEY="joetun.key"
C_R_PORT="50022"

C_L_HOST="127.0.0.1"
C_L_PORT="22"

💡 Укажите ваше имя хоста шлюза в C_HOST= вместо ec2-13-34-43-202.compute-1.amazonaws.com.

💡 Если вы строите туннель к другой машине в локальной сети, укажите ее локальный IP-адрес в C_L_HOST=.

Запустите туннель, но в режиме отладки:

DEBUG=! ./ra
Running AutoSSH in the foreground
++ autossh -M 0 joetun@ec2-13-34-43-202.compute-1.amazonaws.com -R 0.0.0.0:50022:127.0.0.1:22 -i …
…
Authenticated to ec2-13-34-43-202.compute-1.amazonaws.com ([13.34.43.202]:22) using "publickey".
…
debug1: Remote connections from 0.0.0.0:50022 forwarded to local address 127.0.0.1:22
…
debug1: remote forward success for: listen 0.0.0.0:50022, connect 127.0.0.1:22
…

👍 Если все выглядит хорошо и нет явных сообщений об ошибках, то туннель работает.

Не закрывайте ./ra, откройте новое окно терминала и двигайтесь дальше.

С помощью обычного SSH-клиента подключитесь к общедоступному (прослушиваемому) концу туннеля. Когда вас попросят подтвердить подлинность ключа хоста, введите yes:

ssh joe@ec2-13-34-43-202.compute-1.amazonaws.com -p 50022
joe@linuxvm:~$

Если вы видите это приглашение, поздравляем — вы только что подключились к виртуальной машине Linux через туннель.

Вернитесь к исходному терминалу ./ra и остановите скрипт, нажав Ctrl+C.

Теперь давайте запустим туннель в фоновом режиме:

./ra-ctl start
Starting AutoSSH
AutoSSH is running, PID 2337

Проверьте еще раз с помощью команды ssh …, написанной выше.

👍 Работает? Значит все хорошо. Что у нас в итоге получилось:

  1. Скрипт ra работает в фоновом режиме, запущенный с ./ra-ctl start.
  2. Публичный (слушающий) конец туннеля развернут по адресу ec2-13-34-43-202.compute-1.amazonaws.com:50022. Любой, кто знает пару IP:порт, может подключиться, пока туннель работает.

Затем, если вы хотите, чтобы туннель запускался автоматически при загрузке, выполните эти шаги.

Или, если вы хотите повысить безопасность туннеля и настроить его на запуск по требованию, выполните эти шаги.

🔝

Настройка туннеля: Удалённый доступ (WSL)

📝 Требования:

  1. Ваша версия Windows поддерживает подключения к ней с удаленным рабочим столом.
  2. В вашей системе Windows включен удаленный рабочий стол.
  3. У вас есть еще одна машина с клиентом удаленного рабочего стола, с которого вы можете подключиться через туннель, чтобы протестировать его.
  4. Вы успешно выполнили шаги “Настройка клиента (Linux или WSL)”.
  5. Вы успешно подключились к своему ПК с помощью клиента удаленного рабочего стола по локальной сети.

💡 Некоторые версии Windows, например Home, не разрешают входящие подключения к удаленному рабочему столу. Брандмауэр или антивирус также могут вмешиваться. Пожалуйста, не игнорируйте предварительные условия с 3 по 5. Если вы их пропустите, вы рискуете потратить время на ненужную отладку.

Откройте терминал WSL. Войдите в каталог Tunkit:

cd ~/tunkit

Создайте конфиг для скрипта ra и отредактируйте его:

cp -n ra.d/conf.sh.example ra.d/conf.sh &&
${EDITOR} ra.d/conf.sh

Конфигурация, ra.d/conf.sh, выглядит так:

set -e

C_HOST="ec2-13-34-43-202.compute-1.amazonaws.com"
C_USER="joetun"
C_KEY="joetun.key"
C_R_PORT="50389"

C_L_HOST=`ip route show default | awk '{ print $3 }'`
C_L_PORT="3389"

set +e

💡 Укажите ваше имя хоста шлюза в C_HOST= вместо ec2-13-34-43-202.compute-1.amazonaws.com.

💡 Если вы строите туннель к другой машине в локальной сети, укажите ее локальный IP-адрес в C_L_HOST=.

Запустите туннель, но в режиме отладки:

DEBUG=! ./ra
Running AutoSSH in the foreground
++ autossh -M 0 joetun@ec2-13-34-43-202.compute-1.amazonaws.com -R 0.0.0.0:50389:172.17.80.1:3389 -i …
…
Authenticated to ec2-13-34-43-202.compute-1.amazonaws.com ([13.34.43.202]:22) using "publickey".
…
debug1: Remote connections from 0.0.0.0:50389 forwarded to local address 172.17.80.1:3389
…
debug1: remote forward success for: listen 0.0.0.0:50389, connect 172.17.80.1:3389
…

👍 Если все выглядит хорошо и нет явных сообщений об ошибках, то туннель работает.

Продолжайте работать ./ra. С другого компьютера с помощью клиента удаленного рабочего стола подключитесь к общедоступному (прослушиваемому) концу туннеля ec2-13-34-43-202.compute-1.amazonaws.com:50389.

Если вы видите свой компьютер в сеансе удаленного рабочего стола, поздравляем.

Вернитесь к исходному терминалу ./ra и остановите скрипт, нажав Ctrl+C.

Теперь давайте запустим туннель в фоновом режиме:

./ra-ctl start
Starting AutoSSH
AutoSSH is running, PID 5347

Проверьте соединение с другой машины еще раз.

👍 Работает? Значит все хорошо. Что у нас в итоге получилось:

  1. Скрипт ra работает в фоновом режиме, запущенный с ./ra-ctl start.
  2. Публичный (слушающий) конец туннеля развернут по адресу ec2-13-34-43-202.compute-1.amazonaws.com:50389. Любой, кто знает пару IP:порт, может подключиться, пока туннель работает.

Затем, если вы хотите, чтобы туннель запускался автоматически при загрузке, выполните эти шаги.

Или, если вы хотите повысить безопасность туннеля и настроить его на запуск по запросу, выполните эти шаги.

🔝

Настройка туннеля: Создание клона ранее созданного туннеля (Linux или WSL)

📝 Требования:

  1. Вы успешно выполнили шаги “Настройка туннеля: Удалённый доступ”: 🎲Linux, 🎲WSL.

Допустим, у нас есть несколько серверов-шлюзов в Интернете, и мы хотим использовать все серверы для дублирования наших туннелей удаленного доступа. Туннель ra уже настроен, теперь мы хотим построить туннель xyz по той же модели.

Войдите в каталог Tunkit:

cd ~/tunkit

Создайте набор каталогов и файлов:

mkdir xyz.d xyz-mon.d &&
ln -s ra xyz &&
for P in ctl mon mon-ctl; do cp -d ra-${P} xyz-${P}; done

Создайте конфиг для скрипта xyz и отредактируйте его:

cp -nt xyz.d ra.d/conf.sh &&
${EDITOR} xyz.d/conf.sh

Укажите необходимые настройки в xyz.d/conf.sh, как описано в основной главе “Настройка туннеля: Удалённый доступ” (🎲Linux, 🎲WSL). Настройте, отладьте и запустите туннель.

Что у нас в итоге получилось:

  1. Скрипт xyz готов к использованию, управляется скриптом ./xyz-ctl.
  2. Чтобы настроить монитор по требованию, выполните шаги “Настройка туннеля: Удалённый доступ по требованию (Linux или WSL)”, используя xyz-mon вместо ra-mon.

🔝

Настройка туннеля: Удалённый доступ по требованию (Linux или WSL)

📝 Требования:

  1. Вы успешно выполнили шаги “Настройка сервера: Веб-сайт семафора на базе Nginx”.
  2. Вы успешно выполнили шаги “Настройка туннеля: Удалённый доступ”: 🎲Linux, 🎲WSL.

Допустим, мы построили туннель удаленного доступа (🎲Linux, 🎲WSL), настроил автозапуск (🎲Linux, 🎲WSL) и радуюсь. Но как насчет безопасности, особенно когда речь идет о полном контроле над машиной по SSH или RDP? Что, если комбинация IP:порт, указывающая на нашу внутреннюю и, следовательно, менее защищенную машину, каким-то образом станет известна злоумышленнику? А если он угадает или иным образом узнает наш простой логин и пароль? Опять же, сам факт того, что мы в какой-то момент решили предоставить доступ к внутреннему ресурсу через туннель предполагает в целом более низкий уровень безопасности.

Скорее всего, ресурс, к которому мы предоставляем доступ (чаще всего себе) давно используется исключительно в нашей локальной сети, а пароли, чисто исторически, если и назначаются, то простые.

Чтобы справиться со всем этим, Tunkit позволяет значительно повысить уровень безопасности туннелей удаленного доступа, позволяя нам включать и отключать их по требованию.

⚠️ Если вы настраиваете туннель для постоянного производственного доступа к критически важной инфраструктуре, например, к вашему основному компьютеру на работе, выполнение шагов этого сценария крайне желательно с точки зрения безопасности.

Что ж, приступим.

Если вы ранее настроили автозапуск туннеля (🎲Linux, 🎲WSL), теперь пришло время его надежно отключить: 🎲Linux, 🎲WSL.

Мы уже настроили веб-сайт семафора secret.joescompany.com ранее. Давайте создадим на нем семафор и посмотрим, работает ли он.

⚠️ Не игнорируйте этот шаг, каким бы простым он вам ни казался. Если вы настраиваете туннель для производственного использования

  • семафор должен быть пуленепробиваемым. Тот, кто контролирует семафор, контролирует туннель.*

Поднимите семафор, создав пустую страницу сайта:

ssh joe@secret.joescompany.com "cd ~/www/secret.joescompany.com/html && mkdir -p powah && touch powah/uno"

Проверка снаружи:

curl -fk https://secret.joescompany.com/powah/uno; echo code:$?
code:0

👍 Отлично. Теперь опустите семафор:

ssh joe@secret.joescompany.com "rm ~/www/secret.joescompany.com/html/powah/uno"

Проверить снова:

curl -fk https://secret.joescompany.com/powah/uno; echo code:$?
curl: (22) The requested URL returned error: 404 Not Found
code:22

Теперь семафор не работает, как мы и хотели.

Теперь давайте перейдем к настройке туннельного монитора.

💡 туннельный монитор — это скрипт, который следит за семафором в Интернете, и запускает предварительно настроенный туннель, когда семафор активен, или останавливает туннель, когда семафор выключается.

💡 Связь между сценарием монитора и сценарием туннеля определяется их именами файлов. Таким образом, ra-mon связано с ra. Аналогично, xyz-mon будет соединено с xyz и так далее.

Войдите в каталог Tunkit:

cd ~/tunkit

Создайте конфиг для скрипта ra-mon и отредактируйте его:

cp -n ra-mon.d/conf.sh.example ra-mon.d/conf.sh &&
${EDITOR} ra-mon.d/conf.sh
# Semaphore. Must be HTTPS.
C_SEMA_URL="https://secret.joescompany.com/powah/uno"

Запустите скрипт монитора:

./ra-mon-ctl start
Monitor is running, PID 3298

В новом окне терминала просмотрите журнал монитора в реальном времени:

cd ~/tunkit &&
./ra-mon-ctl log

Используя свободный терминал, поднимите семафор:

ssh joe@secret.joescompany.com "cd ~/www/secret.joescompany.com/html && mkdir -p powah && touch powah/uno"

Журнал монитора должен пополняться такими сообщениями:

[2023-01-26 19:01:30] Semaphore is up, triggering START
Starting AutoSSH
AutoSSH is running, PID 32823

Кроме того, в управляющем сценарии должно быть указано, что туннель запущен:

./ra-ctl status
AutoSSH is running, PID 32823

Опустите семафор:

ssh joe@secret.joescompany.com "rm ~/www/secret.joescompany.com/html/powah/uno"

Журнал монитора должен пополняться такими сообщениями:

[2023-01-26 19:07:00] Semaphore is down, triggering STOP
Stopping AutoSSH, PID 32823
AutoSSH is not running

👍 Если все так, как указано выше, то семафор и скрипт монитора работают корректно.

💡 Если по какой-то причине скрипт монитора ведет себя некорректно, вы можете запустить его на переднем плане в режиме отладки:

DEBUG=! ./ra-mon

Что у нас в итоге получилось:

  1. Туннель ra теперь контролируется монитором, который следит за семафором в Интернете.
  2. Ручное управление через ./ra-ctl start и ./ra-ctl stop теперь бессмысленно. Например, если семафор не работает, и вы вводите ./ra-ctl start, монитор мгновенно остановит туннель. Верно и обратное: пока семафор включен, монитор будет запускать туннель ra, даже если вы остановите его вручную.

Далее, если вы хотите, чтобы монитор автоматически запускался при загрузке, выполните следующие действия: 🎲Linux, 🎲WSL.

🔝

Настройка туннеля: Многоканальный удалённый доступ по требованию (Linux или WSL)

📝 Требования:

  1. Все предпосылки “Настройка туннеля: Удалённый доступ по требованию (Linux или WSL)”.
  2. Вы успешно выполнили шаги “Настройка туннеля: Удалённый доступ” (🎲Linux, 🎲WSL) для создать два независимо работающих туннеля: ra1 и ra2.

основная глава объясняет, что такое монитор по требованию, когда он полезен и как его настроить для одного туннеля. Если вы не читали, пожалуйста.

Здесь мы описываем сценарий, в котором несколько туннелей управляются одним семафором. Конечно, мы можем запустить несколько мониторов (ra1-mon, ra2-mon, …), которые следят за одним и тем же семафором, но это будет расточительно с точки зрения управляемости, трафика и количества запущенных процессов.

Поэтому Tunkit включает монитор raduo-mon, который мы здесь описываем. Этот монитор наблюдает за семафором и управляет несколькими туннелями, настроенными в теле скрипта.

По умолчанию это ra1 и ra2, но набор можно расширить несколькими простыми изменениями в raduo-mon:

#--------------------------------------- Configuration

ALLSEQ=`seq 1 2`
c1() { ./ra1-ctl "$@" 2>&1 | ppipe "ra1-ctl: "; }
c2() { ./ra2-ctl "$@" 2>&1 | ppipe "ra2-ctl: "; }
# Add `c3()` and edit `ALLSEQ` to control yet another tunnel.

Некоторые из моих серверов контролируют 8-10 туннелей с raduo-mon.

Шаги по настройке такие же, как и в главной главе, за исключением следующих отличий:

  • Имя файла монитора по запросу raduo-mon.
  • Имя файла сценария управления raduo-mon-ctl.
  • Имя каталога данных raduo-mon.d/.

Далее, если вы хотите, чтобы монитор автоматически запускался при загрузке, выполните следующие действия: 🎲Linux, 🎲WSL.

🔝

Настройка ОС: Автозапуск туннеля при загрузке (Linux)

💡 Здесь мы описываем распространенный сценарий настройки службы для автоматического запуска при загрузке в современной системе Linux. В качестве примера мы используем SOCKS-туннель.

📝 Требования:

  1. Наша система Linux использует systemd для управления запуском служб во время загрузки.
  2. Пользователь joe правильно настроил туннель SOCKS.

В домашнем каталоге joe создайте юнит-файл для новой службы systemd:

cd &&
mkdir -p .config/systemd/user &&
${EDITOR} .config/systemd/user/tunkit-socks.service
[Unit]
Description=Tunkit SOCKS

[Service]
Type=forking
Restart=on-failure
PIDFile=%h/tunkit/socks.d/autossh.pid
ExecStart=-%h/tunkit/socks-ctl start
ExecStop=%h/tunkit/socks-ctl stop

[Install]
WantedBy=default.target

Включите услугу:

systemctl --user enable tunkit-socks
Created symlink /home/joe/.config/systemd/user/default.target.wants/tunkit-socks.service → /home/joe/.config/systemd/user/tunkit-socks.service.

Перезагрузка. После этого проверьте, запущена ли служба:

systemctl --user status tunkit-socks
● tunkit-socks.service - Tunkit SOCKS
     Loaded: loaded (/home/joe/.config/systemd/user/tunkit-socks.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2023-01-18 17:11:59 UTC; 7min ago
    Process: 1280 ExecStart=/home/joe/tunkit/socks-ctl start (code=exited, status=0/SUCCESS)
   Main PID: 1337 (autossh)
     CGroup: /user.slice/user-1002.slice/user@1002.service/tunkit-socks.service
             ├─1337 /usr/lib/autossh/autossh -M 0    joetun@ec2-13-34-43-202.compute-1.amazonaws.com -D 0.0.0.0:1080 -i /home/joe/tunkit>
             └─1339 /usr/bin/ssh -D 0.0.0.0:1080 -i /home/joe/tunkit/keys/joetun.key -N -o StrictHostKeyCheck>

Jan 18 17:11:58 joehost systemd[1274]: Starting Tunkit SOCKS...
Jan 18 17:11:59 joehost socks-ctl[1321]: Starting AutoSSH
Jan 18 17:11:59 joehost socks-ctl[1280]: AutoSSH is running, PID 1337
Jan 18 17:11:59 joehost systemd[1274]: Started Tunkit SOCKS.

На всякий случай проверьте, работает ли ручной перезапуск:

systemctl --user restart tunkit-socks &&
systemctl --user status tunkit-socks

Если все выглядит нормально, то сервис работает.

💡 Если что-то не работает, попробуйте эти диагностические команды:

journalctl --user
journalctl --user -u tunkit-socks
systemctl --user --failed

В дополнение к вышесказанному, я настоятельно рекомендую прочитать эту статью на DigitalOcean: Understanding Systemd Units and Unit Files Это очень подробный и продуманный материал, объясняющий, как работают systemd юнитов.

🔝

Для скрипта удалённого доступа (ra)

Шаги по настройке такие же, как и в основной главе, за исключением следующих отличий:

  • Юнит-файл для systemd называется .config/systemd/user/tunkit-ra.service и имеет следующее содержимое:

    [Unit]
    Description=Tunkit RA
    
    [Service]
    Type=forking
    Restart=on-failure
    PIDFile=%h/tunkit/ra.d/autossh.pid
    ExecStart=-%h/tunkit/ra-ctl start
    ExecStop=%h/tunkit/ra-ctl stop
    
    [Install]
    WantedBy=default.target
    
  • Команда для включения службы:

    systemctl --user enable tunkit-ra
    
  • Команда для проверки службы после перезагрузки:

    systemctl --user status tunkit-ra
    

🔝

Для скрипта-монитора (ra-mon)

Шаги по настройке такие же, как и в главной главе, за исключением следующих отличий:

  • Юнит-файл для systemd называется .config/systemd/user/tunkit-ra-mon.service и имеет следующее содержимое:

    [Unit]
    Description=Tunkit RA monitor
    
    [Service]
    Type=forking
    Restart=on-failure
    PIDFile=%h/tunkit/ra-mon.d/monitor.pid
    ExecStart=-%h/tunkit/ra-mon-ctl start
    ExecStop=%h/tunkit/ra-mon-ctl stop
    
    [Install]
    WantedBy=default.target
    
  • Команда для включения службы:

    systemctl --user enable tunkit-ra-mon
    
  • Команда для проверки службы после перезагрузки:

    systemctl --user status tunkit-ra-mon
    

🔝

Для многоканального скрипта-монитора (raduo-mon)

Шаги по настройке такие же, как и в основной главе, за исключением следующих отличий:

  • Юнит-файл для systemd называется .config/systemd/user/tunkit-raduo-mon.service и имеет следующее содержимое:

    [Unit]
    Description=Tunkit RAduo monitor
    
    [Service]
    Type=forking
    Restart=on-failure
    PIDFile=%h/tunkit/raduo-mon.d/monitor.pid
    ExecStart=-%h/tunkit/raduo-mon-ctl start
    ExecStop=%h/tunkit/raduo-mon-ctl stop
    
    [Install]
    WantedBy=default.target
    
  • Команда для включения службы:

    systemctl --user enable tunkit-raduo-mon
    
  • Команда для проверки службы после перезагрузки:

    systemctl --user status tunkit-raduo-mon
    

🔝

Отключение автозапуска

В зависимости от того, какой systemd юнит-файл вы создали ранее, выполните команды:

  • Для сценария socks:

    systemctl --user stop tunkit-socks &&
    systemctl --user disable tunkit-socks &&
    systemctl --user status tunkit-socks
    
  • Для сценария ra:

    systemctl --user stop tunkit-ra &&
    systemctl --user disable tunkit-ra &&
    systemctl --user status tunkit-ra
    
  • Для сценария ra-mon:

    systemctl --user stop tunkit-ra-mon &&
    systemctl --user disable tunkit-ra-mon &&
    systemctl --user status tunkit-ra-mon
    
  • Для сценария raduo-mon:

    systemctl --user stop tunkit-raduo-mon &&
    systemctl --user disable tunkit-raduo-mon &&
    systemctl --user status tunkit-raduo-mon
    

🔝

Настройка ОС: Автозапуск туннеля при загрузке (WSL)

💡 Здесь мы описываем распространенный сценарий настройки службы для автоматического запуска при загрузке в системе Linux, работающей под управлением WSL. В качестве примера мы используем SOCKS-туннель.

📝 Требования:

  1. Пользователь joe правильно настроил туннель SOCKS.
  2. Пользователь joe может sudo изменять системные настройки Linux.

Отредактируйте или создайте /etc/wsl.conf:

sudoedit /etc/wsl.conf

Найдите или создайте раздел [boot] и добавьте в него параметр command. Если есть другие разделы и настройки, оставьте их как есть.

[boot]
command = "sudo -u joe ~joe/tunkit/socks-ctl start"

Если boot.command уже существует, выполните следующие шаги, чтобы справиться с ним.

Перезапустите экземпляр WSL. В классической командной строке выполните:

wsl --shutdown & wsl echo hey

💡 Если вы используете PowerShell, выполните:

wsl --shutdown ; wsl echo hey

ВМ под управлением Linux остановится, а затем снова запустится. Через несколько секунд (до 10 секунд на медленных машинах) вы увидите hey.

Проверим, запустился ли наш сервис. Откройте терминал WSL и запустите:

~joe/tunkit/socks-ctl status
AutoSSH is running, PID 49

Если все выглядит нормально, то сервис работает.

🔝

Для скрипта удалённого доступа (ra)

Шаги по настройке такие же, как и в основной главе, за исключением следующих отличий:

  • Параметр boot.command в /etc/wsl.conf:

    command = "sudo -u joe ~joe/tunkit/ra-ctl start"
    

    Если boot.command уже существует, выполните следующие действия, чтобы справиться с ним.

  • Команда для проверки службы после перезапуска WSL:

    ~joe/tunkit/ra-ctl status
    

🔝

Для скрипта-монитора (ra-mon)

Шаги по настройке такие же, как и в основной главе, за исключением следующих отличий:

  • Параметр boot.command в /etc/wsl.conf:

    command = "sudo -u joe ~joe/tunkit/ra-mon-ctl start"
    

    Если boot.command уже существует, выполните следующие действия, чтобы справиться с ним.

  • Команда для проверки службы после перезапуска WSL:

    ~joe/tunkit/ra-mon-ctl status
    

🔝

Для многоканального скрипта-монитора (raduo-mon)

Шаги по настройке такие же, как и в основной главе, за исключением следующих отличий:

  • Параметр boot.command в /etc/wsl.conf:

    command = "sudo -u joe ~joe/tunkit/ra-mon-ctl start"
    

    Если boot.command уже существует, выполните следующие шаги, чтобы справиться с ним.

  • Команда для проверки службы после перезапуска WSL:

    ~joe/tunkit/ra-mon-ctl status
    

🔝

Если boot.command уже прописана в /etc/wsl.conf

/etc/wsl.conf — это файл конфигурации с примитивным синтаксисом. Каждая настройка может присутствовать только один раз, и действует только последняя настройка.

Наш boot.command не исключение. Что, если нам нужно выполнить более одной команды, а boot.command уже есть?

Например, мы собираемся добавить ra-ctl start, но command уже установлено:

[boot]
command = "sudo -u joe ~joe/tunkit/socks-ctl start"

Ответ прост. Нам нужно аккуратно добавить («цепочку») новую команду к существующей через && или ;. Например:

[boot]
command = "sudo -u joe ~joe/tunkit/socks-ctl start && sudo -u joe ~joe/tunkit/ra-ctl start"
#command = "sudo -u joe ~joe/tunkit/socks-ctl start"

⚠️ Настоятельно рекомендую не перезаписывать, а закомментировать существующую строку command =, чтобы в случае ошибки можно было быстро восстановить рабочий сетап. Помните, вы редактируете файл с примитивным синтаксисом, и ошибиться очень легко.

Вы можете узнать больше об операторах цепочки && и ; в этой статье на GeeksforGeeks или другом руководстве по оболочке Unix.

🔝

Отключение автозапуска

Изменить /etc/wsl.conf:

sudoedit /etc/wsl.conf

Найдите раздел [boot] и закомментируйте строку command =:

[boot]
#command = "sudo -u joe ~joe/tunkit/socks-ctl start"

При следующей загрузке WSL туннель не запустится.

🔝

Настройка ОС: Автозапуск туннеля при загрузке (Cygwin)

Активируйте диалоговое окно «Выполнить» (Win+R). В появившемся диалоговом окне введите shell:startup и нажмите ENTER.

В появившемся окне создайте новый ярлык. Введите следующее местоположение элемента:

c:\cygwin64\bin\bash.exe -l -c "~/tunkit/socks-ctl start"

💡 Если вы установили Cygwin по пути, отличному от c:\cygwin64, измените указанное выше значение соответствующим образом.

Введите имя ярлыка, например. Tunkit SOCKS. Подтвердите, нажав «ОК».

В следующий раз, когда вы войдете в систему, туннель SOCKS автоматически запустится в фоновом режиме.

⚠️ Приведенные выше шаги предполагают, что туннель запускается, когда пользователь входит в систему в интерактивном режиме. Этот метод не будет работать в сценариях удаленного доступа. Некоторые аспекты этого частично описаны в “Заметки о совместимости (Cygwin)”.

🔝

Разное

Заметки о совместимости (WSL)

На протяжении всего документа термин «WSL» относится к WSL 2. Я никогда не устанавливал Tunkit под WSL 1, хотя думаю, что он будет работать и в этой версии.

🔝

Заметки о совместимости (Cygwin)

Я успешно использую Tunkit под Cygwin, но со временем столкнулся с рядом аспектов, в основном негативных, которые вам придется учитывать, если вы хотите настроить надежные туннели для производственного использования.

Скажем, если вам нужно настроить «быстрый и грязный» туннель для одноразового использования, Cygwin вполне подойдет.

Но если вы хотите настроить расширенные производственные сценарии, такие как “Настройка туннеля: Удалённый доступ”, “Настройка туннеля: Удалённый доступ по требованию” или “Настройка туннеля: Многоканальный удалённый доступ по требованию”, Я бы посоветовал вам уделить минутку и установить WSL. Особенно учитывая, что самые последние версии WSL, особенно под Windows 11, можно установить всего за несколько минут. Если некоторое время назад Cygwin имел преимущество относительно более простой и быстрой установки, то теперь это преимущество исчезло.

Я суммирую известные аспекты совместимости с Cygwin в списке ниже. Предметы отмечены 🍏, 🍊 и 🍎 в зависимости от характера аспекта:

  1. 🍏 Оба пакета autossh и ssh очень стабильны, хотя могут выглядеть немного устаревшими по номеру версии. Все работает без проблем.
  2. 🍏 Автозапуск туннеля после интерактивного входа в машину настраивается без проблем. Для простого туннеля socks работает нормально.
  3. 🍊 Были трудности при попытке настроить автозапуск туннеля без интерактивного входа. Я использовал планировщик заданий (Task Scheduler). Процессы запускаются, но управлять ими из оболочки Cygwin нельзя, так как они принадлежат другому пользователю. Кроме того, необходимо указать некоторые очень специфические настройки, отличные от настроек по умолчанию, если вы хотите, чтобы задача оставалась активной.
  4. 🍎 Были серьезные проблемы с брандмауэром Защитника Windows. Для работы туннеля RDP к той же машине мне пришлось полностью отключить брандмауэр. При этом, если моя машина строила туннель к другой машине в локальной сети, все работало нормально.

Поскольку у меня пока нет достоверных ответов на поставленные выше вопросы, я воздержусь от подробного описания шагов установки Cygwin, за исключением самого простого SOCKS-сценария.

🔝

Продукт является бесплатным для всех. Любая обратная связь приветствуется.

— © 2021-2023 Алексей Фортуна