Основы управления SSH ключами
Узнайте, как правильно использовать ed25519, настраивать права доступа для sshd и использовать файл config для автоматизации в Ubuntu 24.04.
Как работают SSH-ключи
SSH-ключ — это пара файлов: закрытый (private key), который хранится на вашем устройстве, и открытый (public key), который вы копируете на каждый сервер для входа. При подключении сервер использует открытый ключ, чтобы отправить запрос (challenge), на который может ответить только соответствующий закрытый ключ. Закрытый ключ никогда не покидает ваше устройство. Секретные данные не передаются по сети, поэтому взломанный сервер не получит полезной информации. Именно поэтому ключи надежнее паролей. Правильное управление SSH-ключами строится на четырех принципах: один ключ на одно устройство, соблюдение прав доступа к файлам, требуемых sshd, использование файла ~/.ssh/config для автоматизации параметров и своевременное удаление ключа в случае утери ноутбука.
В данном руководстве каждый принцип рассматривается на примере Ubuntu 24.04, хотя большинство советов применимы к любому Linux-серверу и любой современной версии OpenSSH.
Прежде чем начать, важно уточнить терминологию во избежание ошибок. Открытый ключ не является секретным. Его можно вставлять в тикеты, отправлять по электронной почте или публиковать — никто не сможет войти в систему с его помощью. Секретным является закрытый ключ. Для ваших серверов любой, кто скопирует этот файл и знает его пароль (если он установлен), является владельцем учетной записи.
Создание ключа: ed25519 — оптимальный вариант по умолчанию
Выполните команду на своем локальном компьютере, а не на сервере:
ssh-keygen -t ed25519 -C "laptop"-t ed25519 определяет тип ключа. Ed25519 — современный стандарт: такие ключи имеют короткую длину, работают быстро и поддерживаются всеми версиями OpenSSH, начиная с 2014 года. Используйте ssh-keygen -t rsa -b 4096 только в случае необходимости подключения к устаревшим устройствам, которые не поддерживают ed25519. -C "laptop" устанавливает комментарий. Комментарий не влияет на криптографию, но он поможет вам идентифицировать этот ключ в файле authorized_keys через два года. Рекомендуется указать имя устройства, на котором хранится ключ.
ssh-keygen запрашивает путь для сохранения ключа. Примите значение по умолчанию, ~/.ssh/id_ed25519. Затем система запросит пароль (passphrase). Установите пароль; в разделе ниже объясняется, почему это не создает неудобств при повседневной работе. В итоге вы получите два файла: ~/.ssh/id_ed25519 — это закрытый ключ, а ~/.ssh/id_ed25519.pub — открытый ключ. Проверьте содержимое открытой части:
cat ~/.ssh/id_ed25519.pubssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF3k2s0vQx7GdKQhX1yBz... laptopЭто одна строка, содержащая тип ключа, сам ключ и ваш комментарий. Именно эта строка будет сохранена на ваших серверах.
Один ключ на устройство, а не на сервер
Первый вопрос, который возникает у всех: нужен ли новый ключ для каждого сервера? Нет. Создайте один ключ для каждого устройства, с которого вы вводите команды, и добавьте этот публичный ключ на каждый сервер, к которому устройству необходим доступ. Ключ идентифицирует устройство. Файл authorized_keys на каждом сервере содержит список разрешенных устройств.
Эта модель масштабируется, в то время как альтернативные подходы приводят к предсказуемым проблемам. Использование одного ключа на сервер означает, что ноутбук с доступом к двадцати серверам будет содержать двадцать приватных ключей, и вы перестанете понимать, какой за что отвечает. Использование одного общего ключа для всех устройств еще хуже: если ноутбук будет украден, вы не сможете отозвать его доступ, не заблокировав при этом стационарный компьютер, так как у них один и тот же приватный ключ. В этом случае вам придется заменить ключ везде и одновременно распространить его на все устройства.
При использовании одного ключа на устройство потеря ноутбука обойдется вам в одну строку на каждом сервере: удалите строку ноутбука из authorized_keys, и все остальные устройства продолжат работать. Комментарий, установленный с помощью -C, поможет быстро найти нужную строку.
Принцип этой модели: приватный ключ создается на устройстве и уничтожается вместе с этим устройством. Никогда не копируйте приватный ключ на вторую машину и никогда не загружайте его на сервер. Если новому устройству требуется доступ, сгенерируйте на нем новый ключ.
Разместите публичный ключ на сервере
Простой способ — использовать ssh-copy-id, который входит в состав OpenSSH:
ssh-copy-id matt@10.0.0.10Утилита подключается с помощью доступного метода (обычно по паролю), добавляет ваш публичный ключ в файл ~/.ssh/authorized_keys на сервере и создает директорию и файл с корректными правами доступа, если они отсутствуют. Проверьте результат, открыв новое SSH-соединение: сервер должен впустить вас без запроса пароля учетной записи. Если для вашего ключа установлен passphrase, ваша локальная машина может запросить его; этот запрос является локальным и не является паролем сервера.
Если вход по паролю уже отключен, ssh-copy-id не сможет подключиться, поэтому строку нужно добавить вручную. Подключитесь через работающую сессию или веб-консоль вашего провайдера и выполните на сервере следующую команду:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF3k2s0vQx7GdKQhX1yBz... laptop" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keysВставьте ваш публичный ключ вместо текста в кавычках (полная строка из id_ed25519.pub). В файле authorized_keys на каждой строке записан один публичный ключ, это вся база данных доступа: добавление устройства требует добавления строки, а отзыв доступа — удаления строки. На новом сервере этот шаг входит в первые 10 минут работы с новым VPS, непосредственно перед отключением входа по паролю.
Права доступа, блокирующие вход по ключу
Это самая частая причина сбоя входа по ключу. Со стороны клиента ошибка не отображается. В Ubuntu 24.04 процесс sshd по умолчанию запускается с флагом StrictModes yes. Это означает, что сервер отклоняет authorized_keys файл, который может редактировать другой пользователь. Если файл, директория ~/.ssh или ваш домашний каталог доступны для записи кому-либо, кроме вас, sshd проигнорирует ключ. В этом случае клиент просто запросит пароль без объяснения причин. (OpenSSH в Ubuntu допускает только один исключительный случай: файл доступен для записи вашей собственной приватной группе, в которой нет других пользователей. Не полагайтесь на это; используйте указанные ниже режимы). Причина ошибки фиксируется только в логах сервера:
sudo grep 'Authentication refused' /var/log/auth.logВ минимальных образах без rsyslog сервис auth.log отсутствует; та же строка содержится в journal: sudo journalctl -u ssh | grep 'Authentication refused'.
Authentication refused: bad ownership or modes for file /home/matt/.ssh/authorized_keysДля исправления необходимо изменить права доступа и проверить владельца. Выполните команды на сервере от имени затронутого пользователя:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R matt:matt ~/.sshПравило для запоминания: 700 для директории .ssh и 600 для всего содержимого внутри неё. Те же параметры применимы и на вашем локальном компьютере, так как клиент тоже выполняет проверку. Если приватный ключ доступен для чтения другим пользователям, ssh немедленно отклонит его, и в этот раз ошибка будет явно указана:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/matt/.ssh/id_ed25519' are too open.chmod 600 ~/.ssh/id_ed25519 исправляет эту проблему.
~/.ssh/config: отказ от ручного ввода параметров
Файл ~/.ssh/config на вашем компьютере назначает каждому серверу короткое имя и сохраняет параметры, которые вы обычно вводите. Создайте его с правами 600 и добавьте блок Host для каждого сервера:
Host web1
HostName 10.0.0.10
User matt
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Host db1
HostName 10.0.0.11
User matt
Port 2222
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yesТеперь ssh web1 заменяет ssh -p 22 matt@10.0.0.10. То же самое короткое имя будет работать в scp, rsync и git, так как все они считывают этот файл. HostName — это реальный адрес, User избавляет от необходимости вводить имя пользователя, а IdentityFile указывает, какой именно ключ использовать.
Стоит отдельно упомянуть IdentitiesOnly yes, так как этот параметр исправляет распространенную ошибку. Если в agent загружено несколько ключей, клиент предлагает их по очереди, а сервер считает каждое предложение как неудачную попытку входа. При большом количестве ключей вы получите Received disconnect: Too many authentication failures еще до того, как будет предложен нужный ключ. Параметр IdentitiesOnly yes заставляет клиент предлагать только ключ, указанный в IdentityFile, что предотвращает ошибку.
Пароли и ssh-agent
Пароль шифрует файл закрытого ключа на диске. Без пароля любой, кто скопирует файл, сможет сразу начать его использовать. С паролем украденный файл бесполезен, пока не будет угадан пароль. Для ключа на ноутбуке это именно тот уровень защиты, который необходим, так как ноутбуки часто крадут, а резервные копии могут быть скомпрометированы.
Пароль не создает задержек на практике благодаря ssh-agent. Agent хранит расшифрованный ключ в памяти, поэтому вам нужно ввести пароль только один раз за сеанс входа, а все последующие соединения будут мгновенными. Большинство дистрибутивов Linux для рабочих станций и macOS уже запускают agent автоматически. Загрузите ваш ключ в него с помощью команды:
ssh-add ~/.ssh/id_ed25519Команда ssh-add -l выводит список ключей, которые в данный момент хранит agent. Предупреждение: проброс агента (ssh -A) позволяет удаленному серверу использовать ваш agent для дальнейшей аутентификации, пока вы подключены. Включайте эту функцию только для тех серверов, которым вы полностью доверяете, и по умолчанию держите ее выключенной.
Ротация и отзыв: сценарий при утере ноутбука
Отзыв обычного SSH-ключа — это просто удаление соответствующей строки из authorized_keys на каждом сервере, где он используется. Вам не нужно уведомлять центр сертификации или ждать истечения срока действия. Как только строка удалена, вход с этим ключом становится невозможен.
Выполните этот сценарий сейчас, пока нет экстренной ситуации. Выберите сервер, откройте ~/.ssh/authorized_keys и найдите ключ по его комментарию. Удалите строку с помощью редактора или отфильтруйте её по комментарию:
grep -v ' laptop$' ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.tmp
mv ~/.ssh/authorized_keys.tmp ~/.ssh/authorized_keysЗатем проверьте: на устройстве, для которого вы отозвали ключ, вход должен быть невозможен, а на другом устройстве — вход по старому ключу должен по-прежнему работать. Обратите внимание: удаление ключа не завершает уже открытые сессии, так как проверка ключа происходит только при входе. Если вы отзываете ключ из-за кражи устройства, также проверьте who на сервере и завершите все неизвестные вам сессии.
Ротация — это та же операция, но в другом порядке: создайте новый ключ на устройстве, установите его с помощью ssh-copy-id, убедитесь, что новый ключ работает, и только после этого удалите старую строку. Выполняйте это при передаче устройства другому лицу, при подозрении на компрометацию ключа или при увольнении сотрудника. Выполнение этих действий вручную на двух серверах допустимо; для двадцати серверов требуется автоматизация. Инструкция управления несколькими Linux-серверами объясняет, как привести парк устройств к единому состоянию authorized_keys.
Чего не следует делать
- Не используйте один и тот же private key на всех устройствах. В этом случае невозможно отозвать доступ для одного украденного устройства, не заменив ключ на всех остальных.
- Не фиксируйте (commit) private key в git repository, даже в приватном. Автоматизированные сканеры отслеживают публичные репозитории и пытаются использовать утечки ключей в течение нескольких минут после push. Если репозиторий позже станет публичным, вся его история будет скомпрометирована.
- Не загружайте private key вашего ноутбука на сервер для обеспечения доступа к другому серверу. Сгенерируйте отдельный ключ непосредственно на сервере и предоставьте этому ключу необходимые права только там, где это требуется.
- Не вставляйте private key в чаты, электронные письма или тикеты. Для обмена данными используется только public key, то есть файл
.pub.
Когда аутентификация по ключу станет работать стабильно, отключите аутентификацию по паролю. Это предотвратит успешные попытки подбора пароля к вашему серверу. Готовое решение для этой задачи приведено в статье SSH hardening on a VPS.
FAQ
Как работают SSH-ключи без передачи пароля?
Сервер хранит ваш публичный ключ в ~/.ssh/authorized_keys. При входе сервер отправляет запрос (challenge), ваш клиент подписывает этот запрос с помощью закрытого ключа, а сервер проверяет подпись с помощью публичного ключа. Закрытый ключ никогда не покидает ваше устройство, поэтому перехватить его при передаче невозможно, а украденный с сервера ключ не будет пригоден для повторного использования. При взломе сервера утекают только публичные ключи, которые нельзя использовать для входа на другие системы.
Стоит ли использовать один и тот же SSH-ключ для всех серверов?
Использовать один ключ для многих серверов допустимо, если этот ключ хранится только на одном устройстве. Правило гласит: один ключ на одно устройство, а не один ключ на один сервер. Публичный ключ вашего ноутбука должен быть на каждом сервере, к которому нужен доступ с ноутбука, а у стационарного компьютера должен быть свой собственный ключ. Это упрощает отзыв доступа: при потере устройства вам нужно удалить только одну строку на каждом сервере, и остальные устройства продолжат работать.
Какие права доступа должны быть у директории .ssh и файла authorized_keys?
Установите 700 для ~/.ssh и 600 для authorized_keys и для каждого закрытого ключа. Владельцем файлов должен быть пользователь, использующий их. По умолчанию sshd запускается с StrictModes yes, поэтому, если файл или домашний каталог доступны для записи кому-либо, кроме вас, sshd проигнорирует ваш ключ. Единственным признаком ошибки будет запись Authentication refused: bad ownership or modes в системном журнале (auth log или journal).
Как удалить SSH-ключ с сервера?
Удалите строку с ключом из файла ~/.ssh/authorized_keys в учетной записи, для которой он был разрешен. Найдите нужную строку по комментарию (текст после самого ключа). Новые попытки входа с этим ключом будут отклонены, но уже открытые сессии останутся активными. Если устройство было украдено, завершите все активные сессии этого устройства. Повторите процедуру на каждом сервере, куда был скопирован ключ.
Нужно ли устанавливать passphrase на SSH-ключ?
Для ключа на ноутбуке или стационарном компьютере — да. Passphrase шифрует файл ключа, поэтому украденная или утекшая копия сама по себе бесполезна. Использование ssh-agent позволяет вводить пароль один раз за сессию, а не при каждом подключении. Ключи, используемые автоматизацией на сервере, обычно не имеют passphrase, так как для их ввода нет человека; защищайте такие ключи путем ограничения прав доступа учетной записи.