SSH-ключи глубоко
Зачем это нужно
В главе «Файлы, пакеты, SSH» мы подключались к серверу по паролю и один раз сгенерировали ключ, чтобы пароль больше не вводить. Этого хватает, чтобы «работало». Но очень быстро наступает момент, когда «работает» мало: ключей становится два — для чемпионатного сервера и для GitHub; терминал начинает при каждом подключении спрашивать парольную фразу; команда подключения разрастается до ssh -i ~/.ssh/work_key -p 2222 student@192.168.1.10, которую невозможно запомнить. На этой странице разберём механизм ключей до конца: как пара ключей на самом деле доказывает серверу, кто ты, что лежит в каждом файле внутри ~/.ssh, зачем нужен агент и как файл config превращает длинные заклинания в короткое ssh champ.
Эта страница — углубление: сначала пройди главу «Файлы, пакеты, SSH», где ssh и ssh-keygen появляются впервые.
Как пара ключей доказывает, кто ты
Ключ SSH — это всегда пара из двух файлов, которые генерируются одновременно и математически связаны:
- Приватный ключ (private key) — твой секрет. Никогда не покидает твою машину, никому не отправляется, ни в чат, ни в репозиторий.
- Публичный ключ (public key) — открытая половина. Её можно показывать кому угодно: она кладётся на каждый сервер, куда ты хочешь входить.
Механика подключения — по сути «вызов-ответ»:
твоя машина сервер
┌───────────────────┐ ┌────────────────────────┐
│ приватный ключ │ │ authorized_keys: │
│ id_ed25519 │ │ ...твой публичный... │
└────────┬──────────┘ └───────────┬────────────┘
│ 1. «хочу войти как student» │
│ ────────────────────────────────────► │
│ 2. случайный вызов (challenge) │
│ ◄──────────────────────────────────── │
│ 3. подпись вызова приватным ключом │
│ ────────────────────────────────────► │
│ 4. проверка подписи публичным ключом │
│ ◄──────────────── вход разрешён ───── │
Сервер присылает случайные данные, твоя машина подписывает их приватным ключом, сервер проверяет подпись публичным. Подпись, созданную приватным ключом, может проверить только парный публичный — и наоборот, по публичному ключу восстановить приватный практически невозможно. Поэтому перехват публичного ключа злоумышленнику ничего не даёт, а приватный ключ даже не передаётся по сети — сервер его никогда не видит.
Сгенерировать пару мы уже умеем, теперь прочитаем команду целиком:
При генерации команда задаст два вопроса: куда сохранить (по умолчанию ~/.ssh/id_ed25519 — соглашайся) и парольную фразу (passphrase). Парольная фраза шифрует приватный ключ на диске: если ноутбук украдут, файл ключа без неё бесполезен. Это не тот пароль, что у сервера, — сервер о ней вообще не знает.
Что лежит в ~/.ssh
После пары подключений каталог ~/.ssh выглядит так:
| Файл | Что это | Права |
|---|---|---|
id_ed25519 | приватный ключ — секрет | 600 (только владелец, только чтение-запись) |
id_ed25519.pub | публичный ключ — одна строка текста | 644 |
config | твои настройки подключений (разберём ниже) | 600 |
known_hosts | отпечатки серверов, куда ты уже ходил | ведёт сам ssh |
authorized_keys | на сервере: список публичных ключей, кому можно входить | 600 |
Права — не формальность: ssh отказывается использовать приватный ключ, доступный на чтение кому-то кроме владельца, с ошибкой WARNING: UNPROTECTED PRIVATE KEY FILE!. Починка — chmod 600 ~/.ssh/id_ed25519 (вот где пригодилась глава про права).
Доставить публичный ключ на сервер проще всего командой ssh-copy-id student@192.168.1.10: она сама допишет твой .pub в ~/.ssh/authorized_keys на сервере с правильными правами. Руками это то же самое, что дописать одну строку в тот файл.
А known_hosts решает обратную задачу — проверяет сервер: при первом подключении ssh показывает отпечаток (fingerprint) ключа сервера и спрашивает Are you sure you want to continue connecting?. После твоего yes отпечаток запоминается, и если однажды сервер ответит другим ключом, ssh поднимет тревогу REMOTE HOST IDENTIFICATION HAS CHANGED! — либо сервер переустановили, либо кто-то притворяется им.
ssh-agent: ввести парольную фразу один раз
Парольная фраза защищает ключ, но вводить её при каждом git push — мучение. Для этого есть агент — программа ssh-agent, которая один раз расшифровывает приватный ключ и держит его в памяти до конца сеанса; все следующие подключения обращаются к агенту и проходят без вопросов.
eval "$(ssh-agent -s)" # запустить агента (обычно уже запущен системой)
ssh-add ~/.ssh/id_ed25519 # добавить ключ — парольную фразу спросит один раз
ssh-add -l # список ключей, которые агент уже держит
Странная на вид первая строка объясняется просто: ssh-agent -s печатает команды настройки переменных окружения, а eval их выполняет в текущей оболочке — так остальные команды узнают, где искать агента. В Ubuntu с графическим входом агент, как правило, уже запущен, и остаётся только ssh-add.
~/.ssh/config: короткие имена вместо заклинаний
Команда ssh -i ~/.ssh/work_key -p 2222 student@192.168.1.10 — это четыре вещи, которые нужно помнить: ключ, порт, пользователь, адрес. Файл ~/.ssh/config позволяет записать их один раз:
Host champ
HostName 192.168.1.10
User student
Port 2222
IdentityFile ~/.ssh/work_key
После этого всё то же самое делает команда ssh champ — а заодно scp file.txt champ:~/ и любой инструмент поверх ssh, включая git. Разберём поля:
Блоков Host в файле может быть сколько угодно — по одному на каждый сервер. Отступы внутри блока — просто читаемость: ssh их не требует, но все так пишут.
Несколько ключей на одной машине
Типичная ситуация: один ключ для чемпионатного сервера, второй — для GitHub. Ключи не обязаны называться id_ed25519: при генерации задай своё имя файла, например ~/.ssh/github_key. Дальше всё решает config — каждому серверу свой IdentityFile:
Host champ
HostName 192.168.1.10
User student
IdentityFile ~/.ssh/champ_key
Host github.com
User git
IdentityFile ~/.ssh/github_key
Для GitHub псевдоним совпадает с настоящим адресом — так git, который ходит на github.com, автоматически подхватит нужный ключ. Обрати внимание на User git: на GitHub все подключаются пользователем git, а кто именно ты — сервер понимает по предъявленному ключу. Именно поэтому команда проверки выглядит так:
ssh -T git@github.com
и отвечает Hi <твой-логин>! You've successfully authenticated... — ключ и есть твоё имя.
Практика: собери свой ~/.ssh
Учебный терминал не умеет запускать настоящий ssh-keygen, но раскладку файлов — самое частое место ошибок — отрепетировать можно. Собери каталог ~/.ssh руками: создай его, положи внутрь «ключи» и запиши в config блок для сервера champ (используй echo 'текст' >> .ssh/config, чтобы дописывать строки).
- ○ .ssh/champ_key
- ○ .ssh/champ_key.pub
- ○ .ssh/config
Как это устроено под капотом
И набери команды этой страницы руками — на настоящей машине они должны отлетать без подглядывания:
Цель: точность ≥ 90%
ssh-keygen -t ed25519 -C 'oleg@laptop'
Шпаргалка
| Команда / файл | Что делает |
|---|---|
ssh-keygen -t ed25519 -C 'метка' | сгенерировать пару ключей Ed25519 |
ssh-copy-id user@host | доставить публичный ключ в authorized_keys сервера |
chmod 600 ~/.ssh/id_ed25519 | починить права приватного ключа |
eval "$(ssh-agent -s)" | запустить агента в текущей оболочке |
ssh-add ~/.ssh/id_ed25519 | добавить ключ агенту (passphrase — один раз) |
ssh-add -l | какие ключи агент уже держит |
~/.ssh/config | блоки Host: адрес, пользователь, порт, ключ — под коротким именем |
ssh -T git@github.com | проверить ключ для GitHub |
id_ed25519 / id_ed25519.pub | приватный (секрет!) / публичный (можно делиться) |
known_hosts | отпечатки серверов, которым ты уже доверился |
Углубиться
Почему именно Ed25519, а не RSA. Старые руководства учат ssh-keygen -t rsa -b 4096. RSA-ключи по-прежнему работают, но Ed25519 моложе, короче (68 символов публичного ключа против сотен), быстрее и не имеет истории «слабых» вариантов при неудачном выборе длины. Новые ключи имеет смысл делать Ed25519; RSA остаётся для редких старых систем, которые Ed25519 не понимают.
Отпечаток ключа. Команда ssh-keygen -lf ~/.ssh/id_ed25519.pub печатает fingerprint — короткую сводку ключа вида SHA256:.... По ней удобно сверять ключи, не сравнивая длинные строки целиком: тот же отпечаток GitHub показывает в настройках рядом с каждым добавленным ключом.
Агент можно пробрасывать — осторожно. Флаг ssh -A (agent forwarding) позволяет с промежуточного сервера ходить дальше твоим локальным ключом, не копируя ключ на этот сервер. Удобно, но администратор промежуточного сервера в этот момент может пользоваться твоим агентом. Официальная документация прямо советует включать проброс только для доверенных машин; чаще правильный ответ — ProxyJump в config.
Один ключ — не навсегда. Ключи отзываются просто: удалил строку из authorized_keys (или из настроек GitHub) — ключ больше не пускает. Поэтому потерянный ноутбук — не катастрофа, а повод за минуту удалить его ключ со всех серверов. Держать по отдельному ключу на каждую машину — как раз для этого.
Дальше по теме:
- OpenSSH Manual Pages — официальные man-страницы ssh, ssh-keygen, ssh-agent, ssh_config — первоисточник всей этой страницы
- GitHub Docs — Подключение к GitHub с помощью SSH — генерация ключа, добавление в аккаунт и проверка, по-русски
Что должен уметь
- Объяснять на пальцах, как пара ключей доказывает серверу личность и почему приватный ключ не передаётся по сети.
- Называть роль каждого файла в
~/.ssh: ключи, config, known_hosts — и authorized_keys на сервере. - Чинить ошибку
UNPROTECTED PRIVATE KEY FILEи понимать, зачем приватному ключу права 600. - Доставлять публичный ключ на сервер через
ssh-copy-idи объяснять, что она меняет на сервере. - Пользоваться ssh-agent: добавить ключ, посмотреть список, объяснить, зачем нужна конструкция с eval.
- Писать блоки Host в
~/.ssh/config— включая отдельные ключи для разных серверов и для GitHub.
Куда дальше: проверенные ресурсы
-
OpenSSH Manual Pages — man-страницы всего семейства OpenSSH: ssh, ssh-keygen, ssh-agent, ssh-add, ssh_config, sshd.
-
GitHub Docs — Сведения об SSH — зачем GitHub ключи и как ими управлять в аккаунте, по-русски.
-
man ssh_config (Ubuntu) — полный список директив файла config: Host, HostName, IdentityFile, ProxyJump и десятки других.
-
cloud.ru — пошаговая настройка SSH-ключей — тот же путь с ssh-keygen и переносом ключа, разобранный со скриншотами.
-
Видео и материалы сообщества — ниже — ролики по теме и ссылки от студентов и преподавателей смотри в самом низу страницы.
SSH создал в 1995 году финский исследователь Тату Улёнен — после того, как в сети его университета завёлся сниффер паролей. Программа, написанная в ответ на один инцидент, за пару месяцев набрала двадцать тысяч пользователей.
Комментарии
Комментарии появятся после настройки. Нужен аккаунт GitHub — вход прямо в виджете выше.