Лаборатория кодера

Справочник · Терминал и система

SSH-ключи: создать, добавить, пользоваться

Как сделать ключ ed25519, защитить его паролем, подключить ssh-agent, разложить настройки по ~/.ssh/config и понять, что означает предупреждение об изменившемся ключе сервера.

Обновлено · 7 мин чтения

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

Как это устроено

Ключ состоит из двух файлов. Закрытый остаётся только у вас и никуда не копируется. Открытый (с расширением .pub) можно спокойно отдавать: его кладут на сервер или в настройки Git-хостинга. При входе сервер проверяет, что вы владеете закрытым ключом, который соответствует открытому, а сам закрытый ключ по сети не передаётся.

ФайлЧто этоПрава
~/.ssh/id_ed25519закрытый ключ600
~/.ssh/id_ed25519.pubоткрытый ключ644
~/.ssh/configнастройки клиента600
~/.ssh/known_hostsключи серверов, к которым вы уже подключались644
~/.ssh/authorized_keysна сервере: открытые ключи, которым разрешён вход600
~/.ssh/сам каталог700

Создание ключа

bash
ssh-keygen -t ed25519 -C "laptop-2026"
  • -t ed25519 выбирает современный тип ключа: короткий, быстрый и надёжный. Поддерживается OpenSSH с версии 6.5, то есть практически везде.
  • -C задаёт комментарий. Он попадает в конец открытого ключа и помогает потом понять, какой ключ откуда. Удобно писать имя устройства.
  • Программа спросит, куда сохранить. Если ключ для отдельной цели, дайте ему своё имя: -f ~/.ssh/id_work.
  • Затем она попросит парольную фразу. Её стоит задать: если файл ключа украдут, без фразы им не воспользоваться.

Если какая-то старая система не понимает ed25519, используйте RSA длиной не меньше 3072 бит: ssh-keygen -t rsa -b 4096.

Поменять парольную фразу существующего ключа можно без пересоздания: ssh-keygen -p -f ~/.ssh/id_ed25519.

Как добавить ключ на сервер

Самый простой способ, если вход по паролю пока работает:

bash
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server

Команда допишет открытый ключ в ~/.ssh/authorized_keys нужного пользователя и сама поправит права. Вручную то же самое:

bash
cat ~/.ssh/id_ed25519.pub | ssh user@server 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'

Для Git-хостинга открытый ключ вставляется в настройках профиля в разделе SSH-ключей. Показать его, чтобы скопировать:

bash
cat ~/.ssh/id_ed25519.pub

Проверить, что ключ принят, можно командой ssh -T git@адрес-хостинга: обычно в ответ приходит приветствие с вашим именем.

ssh-agent: пароль ключа один раз

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

bash
eval "$(ssh-agent -s)"            # запустить агент, если он ещё не запущен
ssh-add ~/.ssh/id_ed25519         # добавить ключ, спросит фразу один раз
ssh-add -l                        # какие ключи загружены
ssh-add -D                        # выгрузить все
ssh-add -t 4h ~/.ssh/id_ed25519   # загрузить на 4 часа

В большинстве графических окружений Linux и в macOS агент уже запущен. На macOS добавьте в конфиг UseKeychain yes и AddKeysToAgent yes, тогда фраза сохранится в связке ключей.

~/.ssh/config

В конфиге клиента описывают серверы, чтобы вместо длинной команды набирать короткое имя.

text
Host *
    AddKeysToAgent yes
    IdentitiesOnly yes
    ServerAliveInterval 60

Host prod
    HostName 203.0.113.10
    User deploy
    Port 2222
    IdentityFile ~/.ssh/id_ed25519

Host git-work
    HostName git.company.test
    User git
    IdentityFile ~/.ssh/id_work

Теперь ssh prod заменяет ssh -p 2222 -i ~/.ssh/id_ed25519 deploy@203.0.113.10, а имя работает и в scp, rsync и git.

ПараметрЧто задаёт
Hostкороткое имя или шаблон, к которому относится блок
HostNameнастоящий адрес или доменное имя
Userпользователь на сервере
Portпорт, если не 22
IdentityFileкакой ключ использовать
IdentitiesOnly yesпробовать только указанные ключи, а не все из агента
ServerAliveIntervalраз в N секунд проверять, что соединение живо

Порядок блоков важен: для каждого параметра берётся первое найденное значение. Поэтому общий блок Host * с значениями по умолчанию лучше ставить в конец файла, а если он стоит первым, в нём не должно быть того, что вы хотите переопределять ниже.

Два аккаунта на одном Git-хостинге

Частая задача: личный и рабочий аккаунт, у каждого свой ключ. Делается через два имени в конфиге, как git-work выше, и адрес репозитория с этим именем:

bash
git clone git-work:team/project.git
git remote set-url origin git-work:team/project.git

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

known_hosts и отпечатки

При первом подключении клиент показывает отпечаток ключа сервера и спрашивает, доверять ли ему:

text
The authenticity of host 'prod (203.0.113.10)' can't be established.
ED25519 key fingerprint is SHA256:3Q1h0m6...
Are you sure you want to continue connecting (yes/no/[fingerprint])?

Правильный ответ: сверить отпечаток с тем, что показывает сам сервер. На сервере это делается так:

bash
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

После согласия ключ сервера записывается в known_hosts. Если потом ключ поменяется, клиент откажется подключаться с крупным предупреждением REMOTE HOST IDENTIFICATION HAS CHANGED. Обычная причина безобидна: сервер переустановили. Но это может быть и подмена, поэтому сначала выясните, что произошло, и только потом удаляйте старую запись:

bash
ssh-keygen -R prod             # удалить запись о сервере
ssh-keygen -R '[203.0.113.10]:2222'   # для нестандартного порта

Отпечаток своего ключа показывает ssh-keygen -lf ~/.ssh/id_ed25519.pub. Это SHA-256 от содержимого ключа в Base64; что такое хеш и почему по нему нельзя восстановить ключ, рассказано в статье про хеширование.

Когда вход не работает

Подробный вывод клиента почти всегда показывает причину:

bash
ssh -v prod        # -vv и -vvv ещё подробнее
СообщениеЧто проверить
Permission denied (publickey)тот ли ключ предлагается (Offering public key в выводе -v), есть ли он в authorized_keys нужного пользователя
Bad permissions или UNPROTECTED PRIVATE KEY FILEправа на закрытый ключ: chmod 600
Too many authentication failuresагент перебрал слишком много ключей; добавьте IdentitiesOnly yes и укажите IdentityFile
Connection refusedслужба SSH не запущена или слушает другой порт
Connection timed outсервер недоступен по сети или порт закрыт межсетевым экраном

На стороне сервера смотрите журнал: journalctl -u ssh -f (на некоторых системах служба называется sshd). Самая частая серверная причина — слишком открытые права на домашний каталог, ~/.ssh или authorized_keys: в этом случае сервер молча игнорирует ключ. Правильные права перечислены в таблице в начале статьи, а как их выставить, описано в статье про chmod.

Хорошие привычки

  • Один ключ на устройство, понятный комментарий в каждом ключе.
  • Парольная фраза на закрытом ключе плюс агент, чтобы не вводить её постоянно.
  • Раз в год пересматривайте authorized_keys на серверах и удаляйте ключи устройств, которых больше нет.
  • Резервная копия закрытого ключа, если она нужна, хранится в менеджере паролей, а не в облачной папке рядом с фотографиями.
  • После того как вход по ключу проверен, вход по паролю на сервере лучше отключить: PasswordAuthentication no в настройках службы SSH.