Как настроить ssh-agent & SSH туннели и проброс портов

Есть множество способов настроить ssh-agent в Linux. Приведу самый удобный для себя, который нашел относительно недавно.

Для начала, напишу зачем нужен ssh-agent. Представим, что у вас есть несколько ssh ключей, каждый ключ защищен паролем (да, лучше запароливать ключи). Вы решаете соединиться с каким-то сервером и при каждом соединении ssh клиент просит ввести пароль. Неудобно, не так ли?

А что, если вы хотите соединиться с несколькими серверами по цепочке или же скачать какой-то приватный git репозиторий на удаленном сервере? Придется загружать туда свой приватный ssh ключ. Опять неудобно.

Вот тут на выручку и приходит ssh-agent, он же агент ssh. Он безопасно хранит в памяти все ваши ключи, не требует пароль постоянно, и его можно пробрасывать на удаленные сервера без особых усилий (ssh -A).

Как же включить и настроить его?

Для начала убедитесь, что он установлен в системе (на примере Debian-based систем), скорей всего он уже установлен:

sudo apt-get update
sudo apt-get -y install openssh-client

ssh-agent идет в комплекте с ssh клиентом, удобно.

Далее пропишите в ~/.profile следующую строку:

eval `ssh-agent -s`

Почему в ~/.profile? Потому что нам достаточно запустить агент всего лишь единожды для сессии, можно конечно запускать их на каждый bash процесс и т.п., но это излишне.

Что значит эта команда? Она запустит ssh-agent, который выдаст необходимые переменные окружения для shell, которые будут экспортированы во все shell процессы пользователя.

Проверить эти переменные можно вот так:

 └─$ env | grep SSH_
SSH_AUTH_SOCK=/tmp/ssh-Hg0DgkE9cvLu/agent.2346
SSH_AGENT_PID=2347

Мы запустили ssh-agent, но этого еще недостаточно, он ничего не знает про наши ssh ключи. Добавим же их в него. Для этого отредактируем ~/.ssh/config, если у вас его нет, то создайте. Вот сокращенный пример моего конфига:

Host *
    ForwardAgent yes
    AddKeysToAgent yes
    IdentityFile ~/.ssh/id_ecdsa
    IdentityFile ~/.ssh/id_rsa

Первой строкой мы указываем к каким хостам применять данную конфигурацию, как видно, ко всем.

Далее мы разрешаем проброс агента на удаленные сервера. Это не всегда безопасно, поэтому можете отключить эту опцию.

AddKeysToAgent yes самая главная строка, она добавляет ключи в агент, если ключ запаролен, то при любом первом подключении у вас будет запрошен пароль и далее сохранен на протяжении всей сессии.

Строки с IdentityFile указывают нужные мне ключи для использования клиентом ssh.

Вот и всё, для вступления изменений в силу достаточно в терминале выполнить . ~/.profile и попробовать подключиться к любому серверу по ssh, например:

ssh -T git@github.com

Для проверки добавленных ключей в агент, выполните

 └─$ ssh-add -l
256 SHA256:EdQaJRIu22tco6giujxrZhsVH44Io+8gkhfUjfj3lNI insider@localhost (ECDSA)
2048 SHA256:9wUbS3ZM8dHsmcRWc3ZBAeQqzN8kw+78grWFSEyL9To  (RSA)
256 SHA256:Upg/EVhSYoErKdFBVvhKt50dxLJeZtUewn6bpGfQnnE insider@xps13 (ED25519)

SSH туннели и проброс портов

При администрировании серверов часто возникают следующие задачи:

  1. Получить доступ к локальному порту на сервере с рабочей машины
  2. Обеспечить доступ к локальному порту рабочей машины с сервера

Обе эти задачи решаются с помощью туннелирования, но иногда требуется организовать такой туннель быстро и без создания сложной дополнительной инфраструктуры. Решить такую задачу можно с помощью SSH.

Доступ к внутреннему порту сервера

Попробуем подключиться к порту, к которому нет доступа снаружи, но есть доступ с сервера (например, MongoDB, которая слушает порт 27017 на интерфейсе localhost сервера). Для этого используется параметр -L.

ssh -L 9999:localhost:27017 root@serverIP

После аутентификации, у нас на рабочей машине появляется порт 9999, который перенаправлен на порт 27017 локального интерфейса сервера.

Теперь можно подключиться к MongoDB напрямую, как будто она запущена у вас на компьютере. 

mongo localhost:9999 -u user -p password

Туннель прервётся, если вы закроете SSH соединение. Кстати, если оно вам не требуется, а нужен только туннель – можно добавить параметр -N.

ssh -L 9999:localhost:27017 root@serverIP -N

Можно также открывать доступ не к локальному порту сервера, а к удаленному порту другой машины, которая доступна с сервера.

ssh -L 9999:anotherIP:80 root@serverIP -N

В данном примере, вы можете делать запросы на порт 9999, связанный с 80 портом машины anotherIP.

Доступ с сервера на локальный порт

Теперь представим ситуацию, что нужно с сервера обратиться к какому-нибудь сервису, запущенному на локальном компьютере. Например, вам регулярно присылают HTTP запросы по 80 порту на сервер. Вы можете прокинуть локальный веб-сервер со своей рабочей машины (скажем с 3000 порта) на сервер так, что запросы будут идти напрямую к вам. За это отвечает параметр -R.

ssh -R 80:localhost:3000 root@serverIP

После этой команды на сервере откроется 80 порт, запросы на который будут прокидываться вам на 3000.

По умолчанию 80 порт откроется на всех интерфейсах. Если вы желаете выбрать конкретный (скажем 192.168.0.1), его можно указать следующим образом

ssh -R 192.168.0.1:80:localhost:3000 root@serverIP

Цепочка туннелей через несколько узлов

Если нужно пробросить на свою машину локальный порт с сервера №2, доступ к которому по SSH есть только с сервера №1, можно построить цепочку из SSH туннелей

server1# ssh -L 9999:localhost:27017 root@server2 client# ssh -L 9999:localhost:9999 root@server1

Можно воспользоваться однострочной командой. 

ssh -L 9999:localhost:9999 root@server1 ssh -L 9999:localhost:27017 -N root@server2

А в случае, если у вас есть SSH ключи для доступа к серверу №2, вы можете построить защищенный туннель так, что ваш трафик не будет виден на сервере №1.

ssh -L 9998:server2:22 -N root@server1 ssh -L 9999:localhost:27017 -N -p 9998 root@localhost

В данном примере вы пробрасываете себе на порт 9998 порт с сервера №2, обращаясь к нему через сервер №1. А затем пробрасываете порт 27017 с сервера №2 на локальный 9999. В данной конфигурации вам уже не нужен сервер №1, так как порт SSH уже у вас на локальном 9998

SOCKS прокси

С помощью параметра -D можно создать на локальной машине сокет для прослушивания динамического порта.

ssh -D localhost:8123 root@serverIP

Теперь достаточно добавить хост localhost и порт 8123 в браузер для использования в качестве прокси.

Заключение

Мы научились пробрасывать локальный порт на сервер и серверный порт на локальную машину с помощью SSH. И хотя это не слишком production ready решение, но на этапе разработки часто оказывается практичным и работает стабильно.

Источники:

https://www.prolinux.org/post/2021/02/11/kak-nastroit-ssh-agent/

https://codex.so/ssh-tunnel

Was this helpful?

0 / 0