По ходу настройки
keyring
для Nextcloud-клиента (см. Linux: Nextcloud клиент, qtkeychain и ошибка «The name org.freedesktop.secrets was not provided by any .service files») – решил навести порядок в своих SSH-ключах, которых много, и аутентификация иногда преврашается в достаточно геморройный процесс.
В целом, для упрощения работы можно использовать системное хранилище секретов – gnome-keyring
, либо KeeyPassXC, про них в другой раз.
В этом посте посмотрим примеры работы с ssh-agent
и то, как можно хранить и управлять запароленными RSA-ключами без таких бекендов.
Примеры выполняются на Arch Linux (и, местами, для проверки – на Manjaro Linux с Budgie DE).
Содержание
ssh-agent
ssh-agent предназначен для управления SSH-ключами пользователя и их паролями, что бы не вводить пароль к ключу каждый раз при использовании.
Запуск агента
Выполняем:
Для работы клиентов важны переменные, которые задаются агентом:
SSH_AGENT_PID
: с PID процесса сssh-agent
, которая будет использоваться при, например,ssh-agent -k
для остановки агентаSSH_AUTH_SOCK
: указывает на путь к unix-сокету, который будут использовать другие процессы для коммуникации сssh-agent
Что бы запустить агента без вывода всей этой информации – используем:
Вариантов запуска много, рассмотрим их в конце, в Запуск ssh-agent и несколько консолей.
Примеры
Рассмотрим базовые примеры использования ssh-agent
.
Создание ключа
Генерируем ключ:
Опции тут:
-t
: тип RSA-b
: длина ключа в битах (по-умолчанию 3072 для RSA)-f
: путь к файлу ключа (по-умолчанию будет~/.ssh/id_rsa
)-C
: комментарий к ключу (по-умолчанию будет [email protected])-P
: пароль для доступа к ключу
Проверка пароля
Что бы проверить пароль ключа – используем -f
для указания ключа, и -y
для вывода информации о ключе, поэтому запросит пароль:
Смена пароля
Что бы изменить пароль, заня старый:
ssh-copy-id
– копирование ключа на сервер
Скопировать ключ можно вручную, получив его публичную часть:
И скопировав содержимое в файл ~/.ssh/authorized_keys
на удалённом хосте.
Другой вариант – используя утилиту ssh-copy-id
, которая, по сути, выполнит всё тоже самое, но при этом ещё и проверит права доступа на каталоги и файлы (самая частая проблема при использовании SSH-ключей для аутентификации):
И пробуем подключиться, используя этот ключ:
ssh-add
Окей, теперь у нас ключ для аутентификации на сервере, и ключ закрыт паролем.
При каждом обращении к серверу – нам придётся вводить пароль заново – Enter passphrase for key ‘/home/setevoy/.ssh/test-key’.
Что бы избежать этого – добавим ключ в ssh-agent
, используя ssh-add
.
Проверим, что агент запущен:
Could not open a connection to your authentication agent
Самая частая ошибка при использовании агента – когда к нему невозможно подключиться, и ssh-add
сообщает:
Первым делом проверяем SSH_AGENT_PID
(или $SSH_AUTH_SOCK
, т.к. запросы от ssh-add
выполняются через сокет, заданный в этой переменной):
Переменная пустая.
ssh-agent
был запущен в другом терминале (об этом тоже поговорим ниже), поэтому перезапустим его.
Для “чистоты эксперимента” – убиваем запущеные инстансы агента:
И запускаем заново:
-s
используем для создания переменных, т.к. не все будут запускать из bash
, а eval
– что бы сразу выполнить експорт переменных (export SSH_AUTH_SOCK
) из output самого ssh-agent
.
Проверяем ещё раз:
И ssh-add
:
Тут всё готово.
Добавление ключа
Выполняем:
Проверка ключей в агенте
Проверяем загруженные в агент ключи, используя -l
:
Удаление ключа
Используем -d
для удаления одного ключа:
Или -D
для удаления всех ключей:
Автоматическое добавление в ssh-agent
Что бы ssh
(и git
, например) всегда добавляли ключ в ssh-agent
без явного ручного вызова ssh-add
– добавьте AddKeysToAgent
в ~/.ssh/config
, указав yes, confirm или ask (см. SSH_ASKPASS
):
Проверяем – сейчас ключей в агенте нет:
Выполняем подключение, вводим пароль ключа:
Отключаемся, проверяем ключи в агенте:
И теперь при повторном подключении – ключ уже будет взят из агента, и пароль вводить не потребуется:
Запуск ssh-agent
и несколько консолей
Одна из основных проблем, это то, что при запуске новой вкладки в Konsole и инициализации новой bash-сесии – там не будет переменной $SSH_AUTH_SOCK
, и ssh-клиент не сможет получить доступ к ключу.
Например, при вызове ssh-add
в новом терминале получим уже упомянутую ошибку “Could not open a connection to your authentication agent“:
~/.bashrc
Вариантов много, например самый простой – добавить в ~/.bashrc
:
if [ -z "$SSH_AUTH_SOCK" ] ; then eval `ssh-agent -s` ssh-add /home/setevoy/.ssh/test-key fi
Но тогда для каждой сессии bash
будет запускаться новый агент.
Ещё одним вариантом запуска через .bashrc
может быть такой:
ssh-add -l &>/dev/null if [ "$?" == 2 ]; then test -r ~/.ssh-agent-env && \ eval "$(<~/.ssh-agent-env)" >/dev/null ssh-add -l &>/dev/null if [ "$?" == 2 ]; then (umask 066; ssh-agent > ~/.ssh-agent-env) eval "$(<~/.ssh-agent-env)" >/dev/null ssh-add /home/setevoy/.ssh/test-key fi fi
Тут выполняется (см. коды ответа ssh-agent
в документации):
- пытается выполнить
ssh-add -l
, перенаправляет весь вывод в/dev/null
- проверяет код выхода предыдущей комнады
- если код == 2 (ошибка подключения к агенту)
- проверяет доступен ли на чтение
~/.ssh-agent-env
, считывает его содержимое, и передаёт его вbash
- повторяет
ssh-add -l
- если код по-прежнему 2:
- создаёт файл
~/.ssh-agent-env
с правами 660 (чтение и запись только владельцу) - запускает
ssh-agent
, и перенаправляет его вывод в файл.ssh-agent-env
- считывает содержимое
.ssh-agent-env
, и передаёт его вbash
- выполняет
ssh-add /home/setevoy/.ssh/test-key
- создаёт файл
- проверяет доступен ли на чтение
- если код == 2 (ошибка подключения к агенту)
Более-менее вариант, т.к. во всех сессиях у нас будет использоваться один и тот же агент (хотя некоторые рекомендуют использовать различных агентов для разных пулов ключей, например для личных ключей – один агент, для рабочих – другой).
systemd
Ещё один вариант – создать systemd
unit-файл и запускать ssh-agent
как сервис, см. Arch Wiki.
Добавляем каталог, если не создан:
И создаём файл ~/.config/systemd/user/ssh-agent.service
:
[Unit] Description=SSH key agent [Service] Type=simple Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK [Install] WantedBy=default.target
Далее, Wiki говорит про файл ~/.pam_environment
, но у меня Openbox и я переменные обычно задаю в .config/openbox/autostart
:
Кстати, вспомнил про такую вещь, как BASH: переменные — передача значений по-умолчанию ${var:-defaultvalue}, замена значений — ${var:+alternatevalue} и сообщений — ${var:?message}
Останавливаем запущенные инстансы агента:
Проверяем значение XDG_RUNTIME_DIR
:
Сейчас задаём переменную $SSH_AUTH_SOCK
вручную:
И запускам агент через systemctl --user
:
Проверяем:
Переменную сокета:
И пробуем ssh-add
:
Работает.
Можно добавить в автозапуск:
~/.xinitrc
Ещё один вариант – запускать из ~/.xinitrc
.
В таком случае, при вызове startx
(как у меня, когда login manager нет, и X.Org запускается вручную, через вызов startx
в консоли) будет запущен агент, а затем – Openbox, см. документацию:
Кроме того, как уже говорилось в начале – вместо самого ssh-agent
можно использовать либо “обёртки”, которые будут “проксировать” запросы от ssh-add
и других клиентов к ssh-agent
, либо полностью заменят ssh-agent
, но об этом – в следующий раз.
Similar posts
Also published on Medium.