Введение


SSH-agent является частью OpenSSH. В этом посте я объясню, что такое агент, как его использовать и как он работает, чтобы сохранить ваши ключи в безопасности. Я также опишу переадресацию агента и то, как она работает. Я помогу вам снизить риск при использовании переадресации агента и поделюсь альтернативой переадресации агента, которую вы можете использовать при доступе к своим внутренним хостам через bastion’ы.

Что такое SSH-agent


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

Агент SSH хранит секретные ключи в безопасности из-за того, что он не делает:

  • Он не записывает никакой информации о ключах на диск.
  • Он не позволяет экспортировать ваши личные ключи.

Секретные ключи, хранящиеся в Агенте, могут использоваться только для одной цели: подписания сообщения.

Но если агент может только подписывать сообщения, как SSH шифрует и расшифровывает трафик?

При первом изучении открытых и закрытых ключей SSH естественно предположить, что SSH использует эти пары ключей для шифрования и дешифрования трафика. Именно так я и думал. Но это не тот случай. Пара ключей SSH используется только для аутентификации во время первоначального соединения.

Например, вот как проверяется ключ пользователя во время SSH-соединения, с точки зрения сервера:

  • Клиент предоставляет серверу публичный ключ.
  • Сервер генерирует и отправляет короткое случайное сообщение, прося клиента подписать его с помощью приватного ключа.
  • Клиент просит агента SSH подписать сообщение и пересылает результат обратно на сервер.
  • Сервер проверяет подпись, используя публичный ключ клиента.
  • Теперь у сервера есть доказательство того, что клиент владеет приватным ключом.

Позже в процессе соединения генерируется набор новых, эфемерных и симметричных ключей, которые используются для шифрования трафика сеанса SSH. Эти ключи могут даже не длиться весь сеанс; событие «rekey» происходит через регулярные промежутки времени.

Протокол агента


SSH использует сокет домена Unix для общения с агентом по протоколу SSH agent. Большинство людей используют ssh-agent, который поставляется с OpenSSH, но есть множество альтернатив с открытым исходным кодом.

Протокол агента настолько прост, что можно было бы написать базовый SSH-agent за день или два. Он имеет только несколько основных операций:

  • Добавить обычную пару ключей (публичный и расшифрованный приватный ключи)
  • Добавить ограниченную пару ключей (публичный и расшифрованный приватный ключи)
  • Добавить ключ (обычный или ограниченный) из смарт-карты (только публичный ключ)
  • Удалить ключ
  • Вывод списка ключей, хранящихся в агенте
  • Подпись сообщения ключом, хранящимся в агенте
  • Блокировка или разблокировка всего агента с помощью пароля

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

Команда ssh-add — это ваш шлюз к агенту SSH. Он выполняет все эти операции, кроме подписи. Когда вы запускаете ssh-add без каких-либо параметров, он будет сканировать ваш домашний каталог на наличие некоторых стандартных ключей и добавлять их в ваш агент. По умолчанию он ищет:

  • ~/.ssh/id_rsa
  • ~/.ssh/id_ed25519
  • ~/.ssh/id_dsa
  • ~/.ssh/id_ecdsa

Как только вы добавите ключи к связке ключей, они будут автоматически использоваться ssh.

ssh-агент и macOS Keychain
ssh-agent, поставляемый вместе с macOS, может хранить парольную фразу для ключей в macOS Keychain, что делает еще более простым повторное добавление ключей к агенту после перезагрузки. В зависимости от настроек Keychain вам все равно может потребоваться разблокировать его после перезагрузки. Чтобы сохранить ключевые парольные фразы в Keychain, выполните команду ssh-add -K [имя файла ключа]. Парольные фразы обычно хранятся в «Local Items». ssh-agent будет использовать эти сохраненные парольные фразы автоматически по мере необходимости.

Что такое переадресация агента


Функция переадресации агента позволяет вашему локальному агенту SSH связаться через существующее SSH-соединение и прозрачно аутентифицироваться на более удаленном сервере. Например, предположим, что вы входите по SSH в инстанс EC2 и хотите клонировать оттуда приватный репозиторий GitHub. Без переадресации агента вам придется хранить копию вашего приватного ключа GitHub на хосте EC2. При переадресации агента SSH-клиент на EC2 может использовать ключи на вашем локальном компьютере для аутентификации на GitHub.

Как работает переадресация агента


Во-первых, немного предыстории. SSH-соединения могут иметь несколько каналов. Вот распространенный пример: интерактивное соединение с bastion-host (jump box) выполняется на одном канале. Когда для соединения включена переадресация агента (обычно с использованием ssh -A), в фоновом режиме открывается второй канал для переадресации любых запросов агента обратно на ваш локальный компьютер.

С точки зрения ssh, нет никакой разницы между удаленным и локальным ssh-agent. SSH всегда смотрит на переменную окружения $SSH_AUTH_SOCK, чтобы найти доменный сокет Unix для агента. При подключении к удаленному хосту с включенной переадресацией агента SSHD создаст удаленный доменный сокет Unix, связанный с каналом переадресации агента, и экспортирует $SSH_AUTH_SOCK, указывающий на него.

image

Переадресация агента связана с определенным риском


Когда вы переадресовываете доменный сокет ssh-agent Unix на удаленный хост, это создает угрозу безопасности: любой человек с root доступом на удаленном хосте может незаметно получить доступ к вашему локальному SSH-agent’y через сокет. Они могут использовать ваши ключи, чтобы выдавать себя за вас на других машинах в сети.

Вот пример того, как это может выглядеть:

image

Как снизить свой риск при переадресации агента


Вот несколько способов сделать переадресацию агента более безопасной:

  • Не включайте ForwardAgent по умолчанию.


Заблокируйте свой ssh-агент, когда вы используете переадресацию агента. ssh-add -x блокирует агент паролем, а ssh-add -X разблокирует его. Когда вы подключены к удаленному хосту с переадресацией агента, никто не сможет проникнуть в ваш агент без пароля.

Или используйте альтернативный агент SSH, который запрашивает вас, когда он используется. Sekey использует Touch ID на macOS для хранения ключей в анклаве безопасности MacBook Pro.

Или вообще не используйте переадресацию агента. Если вы пытаетесь получить доступ к внутренним хостам через bastion, ProxyJump — гораздо более безопасная альтернатива для этого варианта использования. (смотреть ниже)

Используйте ProxyJump: более безопасная альтернатива


Когда вы хотите пройти через bastion-host (jumpbox), вам действительно не нужна переадресация agent’a. Лучший подход — использовать директиву ProxyJump.

Вместо того чтобы перенаправлять agent’a по отдельному каналу, ProxyJump перенаправляет стандартный вход и выход вашего локального SSH-клиента через bastion и далее на удаленный хост. Вот как это работает:

  1. Запустите ssh -J bastion.example.com cloud.computer.internal для подключения к cloud.computer.internal через ваш bastion хост — bastion.example.com. cloud.computer.internal — это имя хоста, которое можно найти с помощью поиска DNS на bastion.example.com.
  2. Ваш SSH клиент использует ключи от вашего агента для подключения к bastion.example.com.
  3. После подключения SSHD к bastion подключается к cloud.computer.internal и передает это соединение вашему локальному SSH-клиенту.
  4. Ваш локальный SSH-клиент снова проходит через соединение, на этот раз с cloud.computer.internal

Вы можете думать об этом как о SSH в сеансе SSH; за исключением того, что ssh никогда не запускается на bastion. Вместо этого sshd подключается к cloud.computer.internal и дает контроль над этим соединением (стандартный вход и выход) обратно в ваш локальный SSH, который затем выполняет второе соединение.

Настройка ProxyJump

Скажем bastion-host это bastion.example.com. Я могу настроить свой ~/.ssh/config так:

Host bastion.example.com
	User carl

Host *.computer.internal
	ProxyJump bastion.example.com
	User carl

Затем я просто запускаю ssh cloud.computer.internal для подключения к внутреннему назначению через bastion — без переадресации агента.

Если ProxyJump не работает…

Более старые версии SSH и SSHD (до версии 7.2, выпущенной в 2016 году) не поддерживают ProxyJump. Но вы можете выполнить эквивалентную операцию, используя ProxyCommand и netcat. Вот вам пример:

ssh -o ProxyCommand="ssh bastion.example.com nc %h %p" cloud.computer.internal

Магия здесь заключается в том, что SSH сам по себе является прокси-сервером, который вы используете для SSH. Часть nc %h %p просто открывает необработанное соединение сокета к cloud.computer.internal на порте 22. Стандартный ввод-вывод родительской команды ssh передается прямо в ProxyCommand, чтобы родительский ssh мог аутентифицироваться на внутреннем хосте через прокси-соединение.



image
Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя онлайн-курсы SkillFactory:



Читать еще