Имеется сервер с доступом к порту 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