User Tools

Site Tools


ssh_forwarding

ssh forwarding

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

Чаще всего используются следующие сценарии проброса SSH:

  • Local TCP forwarding – проброс локального порта на удаленный сервер;
  • Remote TCP forwarding – проброс удаленного порта на локальный компьютер;
  • Двойной SSH туннель – позволяет соединить между собой через SSH сервер компьютеры без выделенных белых IP адресов или находящиеся за NAT (если не подходит решение с OpenVPN)

Используемые флаги

-f # Запросит ssh перейти в фоновый режим только перед выполнением команды.
Это полезно если ssh собирается запросить пароль или парольную фразу, но пользователь хочет
сделать это в фоновом режиме
 
-N # Не выполнять удаленную команду. Это полезно если вы хотите только перенаправить порты
 
-R # Указывает заданный порт на удаленной машине который будет перенаправлен к заданной машине и локальному порту.

Local TCP forwarding

ssh -f -N -R 2222:10.10.10.14:22 username@12.34.56.78

Подключаемся к созданному туннелю. На хосте 12.34.56.78 вводим:

ssh -p2222 username@localhost

И попадаем на хост 10.10.10.14. Таким же образом, можно получить доступ к любому другому ресурсу, например:

ssh -f -N -R 2080:10.10.10.14:80 username@12.34.56.78

Введя на хосте 12.34.56.78

w3m -dump http://localhost:2080

Получим дамп web-ресурса на 10.10.10.14.

Remote TCP forwarding

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

ssh -f -N -L 4080:192.168.0.10:80 nameuser@88.77.66.55

Аналогично, вводим на своём хосте:

w3m -dump http://localhost:4080

И получаем доступ к web-ресурсу узла 192.168.0.10, который находится за хостом 88.77.66.55.

Поддержка туннелей в поднятом состоянии

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

sudo lsof -i -n | egrep '\<ssh\>'
# либо
sudo lsof -i -n | egrep '\<sshd\>'

Не секрет, что связь иногда обрывается, туннели при этом будут отваливаться по таймауту. Чтобы не утруждать себя дополнительным монотонным вбиванием команды на поднятие туннеля и мониторингом этого процесса, автоматизируем его:

crontab -e

И создаём расписание примерно следующего вида:

TUNCMD1='ssh -f -N -R 2222:10.11.12.13:22 username@99.88.77.66'
TUNCMD2='ssh -f -N -R 2080:10.11.12.14:80 username@99.88.77.66'
 
*/5 * * * * pgrep -f "$TUNCMD1" &>/dev/null || $TUNCMD1
*/5 * * * * pgrep -f "$TUNCMD2" &>/dev/null || $TUNCMD2

Сохраняемся. И проверяем:

crontab -l

Из практического опыта – cron-задания на перезапуск недостаточно. Разве что соединение абсолютно стабильно. В реальной жизни встречается в 0% случаев. Даже соединённые напрямую кабелем две сетевые карты легко могут потерять n-ное количество пакетов и tcp-соединение упадёт. Клиент и сервер будут пребывать в святой уверенности, что всё в порядке, просто вторая сторона ничего не передаёт.

Нужен keepalive. Добавлять нужно в /etc/ssh_config, либо в ~/.ssh/config. Интервал и счётчик – по вкусу:

TCPKeepAlive no
ServerAliveInterval 300
ServerAliveCountMax 3

Также, данные опции можно указать при подключении:

ssh -p 2222 -o "TCPKeepAlive no" -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" \
> -R 3306:127.0.0.1:3306 username@99.88.77.66

autossh

Утилита autossh предназначена для мониторинга соединений ssh и их автоматического восстановления в случае разрыва. Входит в репозиторий Ubuntu

sudo apt install autossh

Клиент

Создадим юнит /etc/systemd/system/autossh.service со следующим содержимым

[Unit]
Description=AutoSSH to My Server
After=network.target
 
[Service]
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -N -M 0 -o "ExitOnForwardFailure=yes" -o "ServerAliveInterval=180" -o "ServerAliveCountMax=3" -o "PubkeyAuthentication=yes" -o "PasswordAuthentication=no" -i /root/.ssh/id_rsa -R 2223:localhost:22 tunnel@host_ip
Restart=always
 
[Install]
WantedBy=multi-user.target

Добавляем в автозагрузку и стартуем

systemctl enable autossh
systemctl start autossh

Заходим на хост

ssh -p2223 localhost

Сервер

Для повышения безопасности туннеля, на сервере создадим пользователя без доступа к shell -s /bin/false, но имеющий домашнюю директорию -m

useradd -d /home/tunnel -s /bin/false -m tunnel

Передадим ему ssh ключ:

ssh-copy-id -i ~/.ssh/id_rsa.pub tunnel@host_ip
ssh_forwarding.txt · Last modified: 2023/04/06 10:28 (external edit)