Имеется сервер с доступом к порту 22 с домашнего IP – это будет rtfm-bastion.
За ним, в приватной сети, есть сервер баз данных, доступ к которому разрешён только с bastion хоста – это будет rtfm-db.
Задача: подключаться к серверу баз данных “напрямую”, без дополнительных команд на бастион-хосте (вообще это надо будет для Ansible, но можно использовать и в повседневной работе).
Т.е, вместо того, что подключаться на bastion, и потом на нём в консоли вызывать ssh user@rtfm-db
– использовать одну команду с домашней машины.
Решение: SSH std i/o forwarding
По теме: C: libssh – пример SSH-“клиента” – посмотреть “изнутри” на процесс установления SSH-соединения и сессий в нём.
Содержание
Настройка подключения к Bastion
Сначала – упростим подключение к bastion.
В ~/.ssh/config
вносим:
Host rtfm-bastion Hostname rtfm.co.ua User setevoy IdentityFile /home/setevoy/.ssh/setevoy_main_priv_openssh
Сохраняем, проверяем:
[simterm]
09:40:49 [setevoy@setevoy-arch-home ~] $ ssh rtfm-bastion ... 06:47:08 [setevoy@ip-172-31-43-63 ~]
[/simterm]
SSH Proxy – подключение к DB
Теперь – обновляем ~/.ssh/config
на своей машине, добавляем подключение к rtfm-db через rtfm–bastion:
Host rtfm-db Hostname 172.31.64.60 User admin ProxyCommand ssh -W %h:%p rtfm-bastion IdentityFile /home/setevoy/Work/RTFM/Bitbucket/aws-credentials/rtfm-prod.pem
Тут 172.31.64.60 будет использоваться для подстановки в %h
команды ProxyCommand
, а -W
указывает на форвадинг standard input/output.
Проверяем:
[simterm]
$ ssh rtfm-db ... admin@ip-172-31-64-60:~$
[/simterm]
SSH Multiplexing
В настройках подключения к bastion – добавляем ControlMaster
, ControlPath
и ControlPersist
:
Host rtfm-bastion Hostname rtfm.co.ua User setevoy IdentityFile /home/setevoy/.ssh/setevoy_main_priv_openssh ControlPath ~/.ssh/cm-%r@%h:%p ControlMaster auto ControlPersist 1m
Кратко – ControlMaster
указывает ssh
использовать уже имеющееся TCP соединение, если оно есть. ControlPath
– путь к файлу сокета, а ControlPersist
– поддерживать вторую открытую сессию, даже если первая сессия уже завершена.
Хороший обзор есть тут>>>.
Если не использовать ControlMaster
, и в двух консолях открыть два подключения к rtfm-db – то мы будем иметь два отдельных TCP-соединения:
[simterm]
10:43:08 [setevoy@setevoy-arch-home ~] $ sudo netstat -tanp | grep ssh tcp 0 0 192.168.1.102:51504 52.208.35.167:22 ESTABLISHED 3879/ssh tcp 0 0 192.168.1.102:51506 52.208.35.167:22 ESTABLISHED 3961/ssh
[/simterm]
Теперь – вернём ControlMaster
, ControlPath
и ControlPersist
, закрываем соединения и открываем их заново, две штуки – проверяем соединения теперь (-t
– отобразить только TCP):
[simterm]
$ sudo netstat -tanp | grep ssh tcp 0 0 192.168.1.102:51050 52.208.35.167:22 ESTABLISHED 11587/ssh
[/simterm]
Используется только одно, а сессии устанавливаются через сокет, указанный в ControlPath
:
[simterm]
$ sudo netstat -anp | grep ssh tcp 0 0 192.168.1.102:51050 52.208.35.167:22 ESTABLISHED 11587/ssh unix 2 [ ACC ] STREAM LISTENING 11026075 11614/ssh: /home/se /home/setevoy/.ssh/[email protected]:22.Ij6tE5Qzr92bore3 unix 2 [ ACC ] STREAM LISTENING 18779 718/systemd /run/user/1000/gnupg/S.gpg-agent.ssh unix 3 [ ] STREAM CONNECTED 11026187 11859/ssh unix 3 [ ] STREAM CONNECTED 11027227 11614/ssh: /home/se /home/setevoy/.ssh/[email protected]:22.Ij6tE5Qzr92bore3 unix 3 [ ] STREAM CONNECTED 11026076 11587/ssh unix 3 [ ] STREAM CONNECTED 11027131 11614/ssh: /home/se /home/setevoy/.ssh/[email protected]:22.Ij6tE5Qzr92bore3
[/simterm]
В каталоге ~/.ssh
на своей машине проверяем сокеты:
[simterm]
10:01:20 [setevoy@setevoy-arch-home ~] $ ls -l .ssh/ total 60 srw------- 1 setevoy setevoy 0 Oct 21 10:01 [email protected]:22
10:01:58 [setevoy@setevoy-arch-home ~] $ file .ssh/cm-setevoy\@rtfm.co.ua\:22 .ssh/[email protected]:22: socket
[/simterm]
Ну и время на открытие сессий.
Без ControlMaster
– подключаемся и сразу выполняем exit
, что бы замерить время только на открытие-закрытие подключения и сессии:
[simterm]
10:39:46 [setevoy@setevoy-arch-home ~] $ time ssh rtfm-db "exit" real 0m1.611s user 0m0.028s sys 0m0.006s 10:43:12 [setevoy@setevoy-arch-home ~] $ time ssh rtfm-db "exit" real 0m1.487s user 0m0.031s sys 0m0.004s 10:43:15 [setevoy@setevoy-arch-home ~] $ time ssh rtfm-db "exit" real 0m1.541s user 0m0.028s sys 0m0.009s
[/simterm]
Полторы секунды в среднем на каждое.
Возвращаем ControlMaster
, повторяем:
[simterm]
10:24:12 [setevoy@setevoy-arch-home ~] $ time ssh rtfm-db "exit" real 0m1.988s user 0m0.027s sys 0m0.006s 10:24:55 [setevoy@setevoy-arch-home ~] $ time ssh rtfm-db "exit" real 0m0.817s user 0m0.034s sys 0m0.004s 10:25:00 [setevoy@setevoy-arch-home ~] $ time ssh rtfm-db "exit" real 0m0.809s user 0m0.027s sys 0m0.011s
[/simterm]
Первый раз почти 2 секунды – установление подключения, “рукопожатие”. Второй и третий раз – меньше секунды, т.к. используется уже имеющееся подключение (которое будет активно ещё ControlPersist 1m
).
Ссылки по теме
Event Sequence of an SSH Connection
Running Ansible Through an SSH Bastion Host
Speeding up SSH Session Creation