Задача: создать обратный тоннель с помощью SSH без установки какого либо программного обеспечения (типа autossh) потому что не всегда это возможно (например, если у вас такой недорогой хостер). Условия:

  • home - домашняя машинка с серым IP

  • server - любой сервер с реальным IP (можно даже VDS за 100р/мес)

  • 22 - порт SSH на домашней машине

  • 2222 - порт, по которому хотелось бы видеть домашнюю машинку на сервере

Итак, начинаем с самого начала…

Конфиг SSH для удобства

Если у вас нет желания постоянно набивать данные, можно в SSH в config добавить нужные данные и просто забыть их как страшный сон. Давайте сделаем конфиг для доступа на сервер

1
 nano ~/.ssh/config
1
2
3
4
 Host server
    HostName 107.6.173.109 (укажите IP сервера)
    Port 2220 (порт SSH на сервере)
    User root (пользователя, под кем вы заходите)

Теперь вы можете просто набирать

ssh server

вместо

ssh root@107.6.173.109 -p2220

Удобно хотя бы в тех случаях, когда порт указать просто не позволяет программа

Авторизация по ключам

Тема стара как мир, но давайте ещё раз вспомним. Итак, генерируем ключи (если они уже есть, система скажет об этом):

ssh-keygen

пароль не задавайте, нам он в дальнейшем не нужен будет

Далее копируем ключик на сервер:

ssh-copy-id server

Всё, теперь проблем с заходом без пароля по SSH быть не должно (если хостер не запретил это, бывает и такое)

Опции для поддержания тоннеля

Идём на домашней машинке в конфиг ssh-клиента

nano /etc/ssh/ssh_config

и добавим в конце

1
2
3
 TCPKeepAlive yes
 ServerAliveInterval 300
 ServerAliveCountMax 3

Хоть какая-то поддержка, но не панацея в том случае, если канал ляжет

Поднимаем тоннель

Теперь поднимем тоннель и проверим, видится ли всё корректно на сервере. Итак, на домашней машинке отдаём команду:

ssh server -R :2222:127.0.0.1:22 -N -C -v

В конце должны увидеть что-то такое:

1
2
 debug1: remote forward success for: listen 2222, connect 127.0.0.1:22
 debug1: All remote forwarding requests processed

На сервере проверяем:

ssh root@127.0.0.1 -p2222

Видим:

1
2
3
 The authenticity of host '[127.0.0.1]:2222 ([127.0.0.1]:2222)' can't be established.
 RSA key fingerprint is 8f:40:9c:5c:b8:21:dd:e4.
 Are you sure you want to continue connecting (yes/no)?

Значит ок, машинка видна. Жмём Y и дальше вбиваем пароль от root домашней машинки. Всё, мы на ней.

Скрипт для пересоединения в случае обрыва

  • Сложнее и без Cron

В принципе, на прошлом шаге можно было бы и остановится, но провайдеы пока далеки от идеала, да и просто пакетики могут куда-то затеряться (солнечные бури, карма и т.д.). Поэтому напишем простой скрипт на домашней машинке, который будет поднимать тоннель в случае разрыва. Итак:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
 myExit() {
 kill $$
 exit $?
}

trap myExit SIGINT

while true
do
 ssh server -R 2222:127.0.0.1:22 -N -C -v
 echo "server crashed on `date`" > /tmp/ssh_tonnel_crached.txt
done

Запускаем его в screen и пусть там висит. Если обрыв, то в файл /tmp/ssh_tonnel_crached.txt добавится дата разрыва и снова попытка восстановить связь. И так, пока сами не прервём выполнение скрипта.

  • Проще, по расписанию в cron и с автозапуском в случае перезагрузки

Screen не везде доступен, да и машинка после ребута его не поднимет. Поэтому делаем скрипт /etc/ssh_tonnel_cron.sh:

1
pgrep -f "ssh server" || ssh server -R 2222:127.0.0.1:22 -N -C -v

в cron можно на раз в 5 минут добавить команду

1
> *\5 * * * * /etc/ssh_tonnel_cron.sh >/dev/null 2>&1