Як керувати ключами SSH у Linux
Дізнайтеся, як працюють ключі SSH: один ed25519 на пристрій, права доступу для sshd, блоки Host у config і відкликання втраченого ключа.
Як працюють ключі SSH
Ключ SSH — це пара файлів: приватний ключ, який зберігається на вашому пристрої, і відкритий ключ, який ви копіюєте на кожен сервер, до якого хочете підключатися. Під час підключення сервер використовує відкритий ключ, щоб надіслати запит, на який може відповісти лише відповідний приватний ключ. Приватний ключ ніколи не залишає ваш пристрій, тому через мережу не передається жоден секрет, а на зламаному сервері немає чого корисного викрасти. Саме тому ключі надійніші за паролі. Належне керування ключами 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. Потім команда запитає парольну фразу. Задайте її; у розділі нижче пояснено, чому в повсякденній роботі це не створює незручностей. У результаті ви отримаєте два файли: ~/.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-сеанс: сервер має впустити вас без запиту пароля облікового запису. Якщо ваш ключ захищений парольною фразою, ваш власний комп’ютер може запросити саме її. Це локальний запит, а не пароль сервера.
Якщо вхід за паролем уже вимкнено, 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, безпосередньо перед вимкненням входу за паролем.
Права доступу, через які не працює вхід за ключем
Це найпоширеніша причина збою входу за ключем, причому на стороні клієнта збій відбувається без повідомлення. За замовчуванням sshd працює з StrictModes yes в Ubuntu 24.04, тому він відмовляється використовувати файл authorized_keys, який можуть редагувати інші користувачі. Якщо файл, каталог ~/.ssh або ваш домашній каталог доступний для запису будь-кому, крім вас, sshd ігнорує ваш ключ і переходить до запиту пароля. Клієнт не показує пояснення. (OpenSSH в Ubuntu допускає лише один вузький виняток: файл може бути доступним для запису групі, до якої належите тільки ви. Не покладайтеся на цей виняток; використовуйте наведені нижче права доступу.) Причина з’являється лише в журналі сервера:
sudo grep 'Authentication refused' /var/log/auth.logУ мінімальному образі без rsyslog файлу auth.log немає; той самий рядок міститься в журналі systemd: 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 потребує окремого пояснення, оскільки він усуває помилку, яку складно зрозуміти. Якщо агент містить кілька ключів, клієнт пропонує їх по одному, а сервер зараховує кожну пропозицію як невдалу спробу. Якщо завантажено достатньо ключів, ви отримуєте Received disconnect: Too many authentication failures ще до того, як буде випробувано правильний ключ. IdentitiesOnly yes змушує клієнт пропонувати лише ключ, указаний у IdentityFile, тому ця помилка не виникає.
Парольні фрази та ssh-agent
Парольна фраза шифрує файл закритого ключа на диску. Без неї будь-хто, хто скопіює файл, одразу зможе ним скористатися. Із парольною фразою викрадений файл непридатний для використання, доки парольну фразу не буде вгадано. Для ключа на ноутбуці це саме той захист, який потрібен, оскільки ноутбуки викрадають, а резервні копії ноутбуків можуть витікати.
На практиці парольна фраза не створює незручностей завдяки ssh-agent. Агент зберігає розшифрований ключ у пам’яті. Тому парольну фразу потрібно вводити один раз за сеанс входу, а всі наступні підключення виконуються без затримки. Більшість дистрибутивів Linux для робочих станцій і macOS уже запускають агент автоматично. Завантажте ключ до нього за допомогою:
ssh-add ~/.ssh/id_ed25519ssh-add -l показує ключі, які агент зараз зберігає. Зверніть увагу: переадресація агента (ssh -A) дає змогу віддаленому серверу використовувати ваш агент для подальшої автентифікації, доки ви підключені. Тому вмикайте її лише для серверів, яким повністю довіряєте, а типово залишайте вимкненою.
Ротація та відкликання: дії в разі втрати ноутбука
Відкликання звичайного 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 у всьому парку серверів.
Чого не слід робити
- Не використовуйте один приватний ключ на всіх своїх пристроях. У такому разі неможливо відкликати доступ лише для одного викраденого пристрою без заміни ключа всюди.
- Не додавайте приватний ключ до git-репозиторію, навіть приватного. Автоматизовані сканери стежать за публічними репозиторіями та намагаються використати витік ключа протягом кількох хвилин після push. Якщо згодом зробити репозиторій публічним, буде розкрито всю його історію.
- Не завантажуйте приватний ключ ноутбука на сервер, щоб цей сервер міг підключатися до іншого сервера. Згенеруйте окремий ключ безпосередньо на сервері та авторизуйте його лише там, де він потрібен.
- Не вставляйте приватний ключ у чат, електронний лист або заявку. Публічний ключ, файл
.pub, — єдина частина, якою можна ділитися.
Коли ключ почне стабільно виконувати вхід, вимкніть автентифікацію за паролем. Тоді постійні спроби вгадати пароль вашого сервера взагалі не матимуть успіху. Drop-in конфігурація для цього наведена в розділі Посилення захисту SSH на VPS.
FAQ
Як працюють SSH-ключі без надсилання пароля?
Сервер зберігає ваш відкритий ключ у ~/.ssh/authorized_keys. Під час входу він надсилає запит, ваш клієнт підписує цей запит закритим ключем, а сервер перевіряє підпис за допомогою відкритого ключа. Закритий ключ ніколи не залишає ваш пристрій, тому його неможливо перехопити під час передавання або повторно використати після викрадення із сервера. Скомпрометований сервер розкриває лише відкриті ключі, які не можна використати для входу будь-куди.
Чи слід використовувати той самий SSH-ключ для всіх серверів?
Використовувати один ключ на багатьох серверах правильно, якщо цей ключ зберігається лише на одному пристрої. Правило таке: один ключ на пристрій, а не один ключ на сервер. Відкритий ключ вашого ноутбука додають на кожен сервер, до якого потрібен доступ із ноутбука, а для настільного комп’ютера використовують окремий ключ. Це спрощує відкликання доступу: якщо пристрій втрачено, з кожного сервера потрібно видалити один ідентифікований рядок, а інші пристрої продовжать працювати.
Які права доступу мають бути для каталогу .ssh і authorized_keys?
Встановіть 700 для ~/.ssh і 600 для authorized_keys та кожного закритого ключа. Власником має бути обліковий запис, який їх використовує. sshd за замовчуванням працює з StrictModes yes, тому якщо файл або домашній каталог доступний для запису будь-кому, крім вас, sshd мовчки проігнорує ваш ключ. Єдиною ознакою буде Authentication refused: bad ownership or modes у журналі автентифікації або журналі сервера.
Як видалити SSH-ключ із сервера?
Видаліть рядок ключа з ~/.ssh/authorized_keys в обліковому записі, для якого цей ключ було авторизовано. Знайдіть потрібний рядок за коментарем — міткою після даних ключа. Нові входи з цим ключем одразу завершаться помилкою, але вже відкриті сеанси залишаться активними. Якщо пристрій було викрадено, також завершіть усі його активні сеанси. Повторіть це на кожному сервері, на який було скопійовано ключ.
Чи потрібна парольна фраза для SSH-ключа?
Для ключа на ноутбуці або настільному комп’ютері — так. Парольна фраза шифрує файл ключа, тому окрема викрадена або витекла копія сама по собі буде непридатною. ssh-agent дає змогу вводити її один раз за сеанс, а не під час кожного підключення. Ключі, які використовує автоматизація без участі оператора на сервері, зазвичай не мають парольної фрази, оскільки нікому її вводити. Захищайте такі ключі, обмежуючи дії, які може виконувати цільовий обліковий запис.