Если вы не всё понимаете на этой странице, то рекомендую сперва прочитать, как настроить простейшие вещи в ssh.
У меня есть около десяти машин (серверов и рабочих станций), на которые мне нужен оперативный доступ. При этом, только к двум возможен доступ по ssh. Остальные находятся за NAT, или закрыты firewall-ами, или не имеют постоянных IP-адресов… Одним словом, — тяжко. Задача: обеспечить к ним доступ.
Мы подними с «недоступных» машин ssh-соединения на «доступные». Поверх этих соединений мы пробросим реверс-туннели, по которым можно будет попасть на «недоступные» машины.
Авторизация у нас, конечно, будет по ключу (подробнее про авторизацию по ключу). Больше того, так как туннель должен подниматься автоматически, мы не можем закрыть ключ паролем. То есть, ключ будет не очень-то защищённым.
Поэтому, по этому ключу мы будем пускать только определённого пользователя, не обладающего большими правами.
Создадим такого пользователя:
useradd -c 'For ssh-tunneling only' -g nobody -m -N -s /home/t/bin/fake-shell t
В файл /home/t/bin/fake-shell
вы можете написать что угодно,
от грубых предупреждений для тех, кто пытается вас ломать,
до чего-нибудь полезного.
Конечно, речь идёт о пользователе на «доступной» машине.
Создаём индивидуальную секцию в
локальном /etc/ssh/sshd_config
:
Match User t
X11Forwarding no
# AllowTcpForwarding no
PermitTTY no
ForceCommand /home/t/bin/fake-shell
Чтобы не залипали туннели, важно добавить в
/etc/ssh/sshd_config
инструкции
ClientAliveCountMax 2
ClientAliveInterval 10
Без них будет наблюдаться такая проблема: если клиент успешно подключился и поднял туннель, а потом молча отвалился (скажем, у него изменился IP), то при повторном подключении он не сможет снова поднять туннель, так как сервер уже поднял туннель для мёртвого клиента и сервер не может определить, что тот клиент умер (так как не пытается это определить).
Этими опциями мы как раз заставляем сервер проверять, жив ли клиент.
Не забываем о полезных опциях:
PasswordAuthentication no
PermitRootLogin no
# по настроениею
AllowUsers t
Добавляйте их с осторожностью и только, если вы понимаете, что делаете.
В ~/.ssh/config
прописываем что-то вроде:
Host tunn
User t
HostName michurin.net
IdentityFile ~/.ssh/id_rsa_open
ServerAliveInterval 10
ServerAliveCountMax 2
ExitOnForwardFailure yes
VerifyHostKeyDNS no
StrictHostKeyChecking no
RequestTTY no
RemoteForward 2080 localhost:22
Здесь michurin.net
— это на «доступный сервер».
Туннель будет подниматься с порта 2080 на
«доступном» сервере и ходить на localhost:22
на «недоступном».
Вам необходимо настроить доступ по
ключу ~/.ssh/id_rsa_open
, не закрытому
паролем. Если доступ работает, то
ставим в cron автоподнималку:
*/5 * * * * ssh -N tunn >>~/cron-ssh.log 2>&1
Если не использовать crontab, то можно как-то так:
nohub sh -c 'while : ; do date; ssh -N rnt; sleep 60; done'
Но это уже как кому нравится.
Кстати, на эту машину вы будете ходить через туннель
на локальный интерфейс. Если другого доступа
не предусматриваеться, то в настройках sshd
можно
указать
ListenAddress 127.0.0.1
Это добавит безопасности системе. А если ваша машина действительно расположена за NAT-ами и firewall-ами, то, очень может быть, что слушать на других интерфейсах вам и не нужно.
Для вашего любимого пользователя на «доступной»
машине (где вы завели пользователя t
), добавляем
в ~/.ssh/config
:
Host home
User me
HostName localhost
Port 2080
Теперь вы можете на «доступной» машине сказать:
ssh home
и попасть на «недоступную». Мы добились, чего хотели.
Дальше можно настроить удобный прямые туннели с «недоступной» на «недоступную», как вам надо. Главное, возможность обеспечена.
Вы можете настроить запуск туннеля через systemd
Создаёте файл, например /etc/systemd/system/tunnel.service
, примерно такого содержания:
[Unit]
Description=Reverse tunnel
After=network.target
[Service]
Type=simple
User=t
Group=users
ExecStart=/usr/bin/ssh -N tunn
Restart=always
RestartSec=60
[Install]
WantedBy=multi-user.target
Перечитываете настройки systemd, проверяете, что запускается, запускаете навсегда:
systemctl daemon-reload
systemctl -l status tunnel
systemctl start tunnel
systemctl -l status tunnel
systemctl enable tunnel