Введение
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
, указывающий на него.
Переадресация агента связана с определенным риском
Когда вы переадресовываете доменный сокет ssh-agent
Unix на удаленный хост, это создает угрозу безопасности: любой человек с root доступом на удаленном хосте может незаметно получить доступ к вашему локальному SSH-agent’y через сокет. Они могут использовать ваши ключи, чтобы выдавать себя за вас на других машинах в сети.
Вот пример того, как это может выглядеть:
Как снизить свой риск при переадресации агента
Вот несколько способов сделать переадресацию агента более безопасной:
- Не включайте
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 и далее на удаленный хост. Вот как это работает:
- Запустите
ssh -J bastion.example.com cloud.computer.internal
для подключения кcloud.computer.internal
через ваш bastion хост —bastion.example.com
.cloud.computer.internal
— это имя хоста, которое можно найти с помощью поиска DNS наbastion.example.com
. - Ваш SSH клиент использует ключи от вашего агента для подключения к
bastion.example.com
. - После подключения SSHD к bastion подключается к
cloud.computer.internal
и передает это соединение вашему локальному SSH-клиенту. - Ваш локальный 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 мог аутентифицироваться на внутреннем хосте через прокси-соединение.
Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя онлайн-курсы SkillFactory:
- Курс «Профессия Data Scientist» (24 месяца)
- Курс «Профессия Data Analyst» (18 месяцев)
- Курс «Python для веб-разработки» (9 месяцев)
Читать еще
Автор: Skillfactory School