Ротація ключів здається простою, поки не стає складною. Ви міняєте ключ, хтось не може развернути реліз, аварійний доступ іншої команди ламається, а «тимчасовий» ключ підрядника, про який ви забули, тихо працює на машині, про яку ніхто вже не пам’ятає.
Саме тут у операціях ви або проводите контрольовану зміну, або отримуєте повільний інцидент із тисячею дрібних порізів. Debian 13 не змінює основ SSH, але це гарний привід перестати ставитися до ключів як до дрібниці на дивані.
Що насправді означає «ротація ключів» у продакшені
У лабораторії ротація SSH-ключів — це охайні два кроки: додати новий ключ, видалити старий. У продакшені це багатосторонній договір, який ви переговораєте під навантаженням.
Ви міняєте не просто файл. Ви змінюєте:
- Ідентичність: які приватні ключі вважаються дійсним підтвердженням вашої особи.
- Авторизацію: які публічні ключі відображаються на які акаунти і з якими обмеженнями.
- Доступність: які бастіони, CI-ранери та облікові записи автоматизації все ще можуть досягати потрібних ресурсів.
- Докази: чи зможете ви пізніше довести, хто мав доступ під час інциденту.
Ротація ключів, виконана добре, має три властивості:
- Відворотність за хвилини (під час розгортання), але невідворотність після закінчення grace-періоду (старі ключі справді мертві).
- Аудитованість: ви можете відповісти «хто може підключитись куди» без ручного grep по всьому середовищу.
- Обмеженість: компрометація одного ключа не призводить до «потрібно міняти все скрізь», якщо це не необхідно.
Ротація ключів, виконана погано, зазвичай означає, що ви міняєте не те (клієнтські ключі vs ключі хоста), видаляєте спочатку, а потім ставите питання, або зберігаєте купу ключів назавжди, бо видалення лякає.
Ключі хоста vs ключі користувача: міняйте те, що треба
Ключі користувача — це ті, що в ~/.ssh/authorized_keys, які впускають людей (чи боти). Ключі хоста — це те, чим клієнт перевіряє, що він говорить зі справжнім сервером.
Ротація ключів хоста — інша процедура з іншим радіусом ураження. Якщо ваш запит звучить «колишній співробітник досі має доступ» або «ключ підрядника витік», вам важливі ключі користувача та їхні шляхи авторизації — не ключі хоста.
Цитата, яку варто тримати в голові
Парафразована ідея — Річард Кук: «Успіх у складних системах часто приходить від людей, які постійно адаптуються, а не від плану, що спрацював як написано.»
Ротація ключів — саме про це: потрібен план, але ви перемагаєте, швидко адаптуючись, коли реальність не сходиться з планом.
Факти та історія: чому SSH-ключі розростаються
Розростання ключів — не моральний провал. Це природний результат інтересів: доставляння продукту перемагає прибирання, і SSH без тертя, якщо його так залишити. Кілька фактів і контексту допоможуть зрозуміти, з чим ви маєте справу.
- SSH замінив rsh/telnet здебільшого завдяки довірі та шифруванню. Ранній виграш був «не в чистому тексті», а не «ідеальне управління ідентичностями». Культура закріпилась.
- OpenSSH десятиліттями віддавав перевагу зручності: per-user
authorized_keysпросто й зручно, тому всі ним користувались, і кластери розрослися навколо нього. - Типи ключів еволюціонували: DSA був поширений, потім фактично застарів; RSA залишався всюди; Ed25519 став «сучасним дефолтом» через компактність і швидкість.
- Forwarding агента задумувався, щоб зменшити розповсюдження ключів, але на практиці часто перетворювався на «віддалена машина може використовувати мій агент», що небезпечно.
- known_hosts — це компроміс UX: trust-on-first-use був практичним, але навчив людей ігнорувати тривожні попередження при зміні ключів хоста.
- authorized_keys може містити опції (обмеження командою, обмеження по IP). Більшість організацій їх не використовує, потім погано відтворює ті ж контролі в іншому місці.
- Короткострокові креденшіали історично важко реалізувати в SSH без додаткових інструментів; довгоживучі ключі стали дефолтом, бо «просто працюють».
- CI/CD погіршив розростання: роботам потрібен доступ, і команди часто «тимчасово» кладуть ключі розгортання на машини. Тимчасове — найдовша одиниця часу в операціях.
- Існують центральні каталоги (LDAP/SSSD тощо), але авторизація SSH часто лишається локальною, бо це просто, а відмови лякають.
Розростання відбувається, бо це зручно, розподілено й невидимо — поки раптом не стає дуже видно.
Швидкий план діагностики (що перевіряти насамперед)
Це поточний поток триажу, коли хтось каже «ми ротуємо ключі і тепер SSH не працює» або «ми відкликали ключі, але доступ усе ще працює». Потрібен швидкий сигнал, а не есе.
Перш за все: це автентифікація, авторизація чи маршрутизація?
- Швидкий клієнтський тест: чи клієнт пропонує очікуваний ключ і що відповідає сервер?
- Логи сервера: що sshd думає про те, що сталося?
- Джерело конфігурації сервера: ви дійсно використовуєте
authorized_keysфайли, чиAuthorizedKeysCommand, чи обидва?
По-друге: знайдіть «джерело істини»
- Якщо авторизація через локальні файли — істина розподілена: потрібно знайти кожен
authorized_keysі будь-які include/альтернативи. - Якщо ви використовуєте команду/SSSD/LDAP — істина централізована: перевірте, чи доступна вона, чи правильна і чи кешується як очікується.
- Якщо ви використовуєте SSH-сертифікати — істина в CA та політиці підпису; відкликання може бути TTL-орієнтоване або за ідентифікатором ключа.
По-третє: підтвердіть, що ви дійсно відкликали те, що вважаєте відкликаним
- Видалення старого ключа з одного місця не допоможе, якщо той самий ключ живе в десяти інших акаунтах або на бастіоні.
- Коментарі ключів брешуть. Відбитки — ні. Завжди звіряйте за відбитком.
- Не забувайте про автоматизацію:
root, користувачі деплою, користувачі Git mirror, резервні акаунти, break-glass акаунти.
Коли застрягли: використовуйте детальні логи клієнта і журнали автентифікації на сервері. Все інше — враження.
Побудуйте реальний інвентар: облікові записи, ключі та шляхи
Перш ніж відкликати — зробіть інвентар. Не тому, що паперовий облік приємний, а тому що відкликання без інвентарю — це як видалити єдиний робочий ключ до сховища о 2:00 ранку.
Де ключі ховаються в системах Debian
/home/*/.ssh/authorized_keys— очевидне місце./root/.ssh/authorized_keys— болюче місце.- Сервісні акаунти з нестандартними домашніми:
/var/lib/*,/srv/*. - Альтернативні місця через
AuthorizedKeysFile(може бути декілька шляхів). - Центральне отримання ключів через
AuthorizedKeysCommand(ключі можуть ніколи не потрапляти на диск по-юзеру). - Точки, куди впадає конфігураційна система (наприклад, фрагменти, що генеруються).
Визначте модель відкликання
Обирайте одну модель на середовище, не по команді.
- Локальні файли, керовані CM: ключі живуть в
authorized_keys, але ними керує система CM (Ansible/Puppet тощо). Просто, але все ще розподілено. - Централізовані ключі:
AuthorizedKeysCommandтягне ключі з центрального сховища (каталог, API, git-backed DB). Чудова аудитованість, більше рухомих частин. - SSH-сертифікати: користувачі автентифікуються короткоживучими сертифікатами, підписаними вашим CA; сервери довіряють CA. Мінімальне розростання, найкраща історія відкликання, якщо TTL налаштовано правильно.
Якщо ви вже достатньо великі, щоб сказати «флот» — сертифікати перемагають. Якщо ви малі, але дисципліновані — керовані локальні файли підходять. Якщо ви середні та хаотичні — централізовані ключі стануть порятунком, якщо їх робити як продакшн, а не як вихідний weekend-проєкт.
Чисте відкликання доступу: техніки без простоїв
Відкликання має бути нудним. Нудьга — це ціль. Секрет у поетапних змінах, щоб ви могли рухатись уперед, а не панікувати назад.
Техніка 1: Додати-потім-видалити з вікном grace
Для людей: додайте новий ключ, перевірте логін, потім видаліть старий після дедлайну. Для автоматизації: потрібна підтримка двох ключів під час rollout та явний час переключення.
Grace-вікно має бути коротким. Дні, не місяці. Довгі вікна — це шлях до одночасної підтримки двох світів назавжди.
Техніка 2: Відкликайте за відбитком, а не по «імені»
Люди копіюють ключі, змінюють коментарі або вставляють не той public key. Завжди ідентифікуйте ключі за відбитком. Розглядайте коментар як метадані від користувача — бо це так і є.
Техніка 3: Використовуйте опції ключа, щоб обмежити радіус ураження
Якщо вам доводиться тримати довгоживучі ключі (і багато компаній так роблять), принаймні обмежте їх. Приклади обмежень:
from="10.0.0.0/8"щоб обмежити джерела за IPcommand="..."для примусової команди (обережно)no-agent-forwarding,no-port-forwarding,no-pty
Це не ідеальні контролі, але вони перетворюють «один витіклий ключ = повний shell звідусіль» на «один витіклий ключ = обмежений доступ з конкретних місць». Це має значення під час реакції на інциденти.
Техніка 4: Вбити доступ на рівні акаунта, коли треба
Якщо користувача звільнено або ключ підтверджено як скомпрометований, чекати на прибирання ключів надто повільно. Заблокуйте акаунт і видаліть ключі.
Блокування акаунта — не заміна гігієни ключів, але це швидкий вимикач мережі.
Техніка 5: Заздалегідь спроєктуйте сценарій break-glass
Потрібен аварійний доступ. Але «всі мають root-ключ на всяк випадок» — це не аварійний доступ; це розростання ключів під виглядом безпеки.
Break-glass має означати: невеликий набір контрольованих ключів/сертифікатів, збережених безпечно, з логуванням і відпрацьованими вправами. Якщо ви ніколи не тестуєте його, він відмовить в момент, коли знадобиться.
Жарт №1: Розростання SSH-ключів як шухляда з мотлохом: одного дня вона знадобиться, але все одно розчарує.
Як уникнути розростання ключів: централізація, опції та SSH-сертифікати
Відкликання — це прибирання. Запобігання розростанню — профілактика. Профілактика дешевша, швидша і менш принизлива.
Централізуйте рішення, а не обов’язково ключі
Багато команд читають «централізація» як «покладіть усі ключі в один файл». Це не мета. Мета — централізувати повноваження: хто може надавати доступ, як це погоджується і як це аудитується.
Добрі практики:
- Конфігураційне управління генерує
authorized_keysзі централізованого інвентарю і примушує його. AuthorizedKeysCommandвитягує ключі з сервісу каталогу і повертає лише актуальні, погоджені ключі.- SSH-сертифікати усувають потребу розповсюджувати публічні ключі користувачів на кожен сервер.
SSH-сертифікати: «дорослий» варіант для флоту
SSH-користувацькі сертифікати (OpenSSH) дозволяють серверам довіряти CA, а не окремим ключам. Користувачі зберігають приватні ключі; CA підписує короткоживучий сертифікат, який говорить «цей ключ дійсний для користувача X протягом N годин з такими-принципалами».
Що змінюється в операціях:
- Ротація — здебільшого політика CA: видавайте короткоживучі сертифікати, і «відкликання» стає «чекати TTL» плюс вимкнення видачі.
- Швидше onboard: сервери вже довіряють CA; новим користувачам не доводиться торкатися кожного хоста.
- Чистіше offboarding: перестаньте підписувати для користувача і дочекайтесь TTL. Немає полювання на ключ по флоту.
Є режими відмови: доступність CA, баги в процесі підпису, проблеми з синхронізацією часу. Але це проблеми, які можна інженерити. Розростання ключів — соціо-технічний безлад, що ніколи не зникає повністю.
Зробіть бастіони нудними і суворими
Бастіон — це місце, де ваша політика доступу стає примусною. Якщо ви дозволяєте підключення прямісінько з ноутбуків до всього, ви обрали хаос.
Сильні дефолти для бастіонів:
- Без agent forwarding, якщо немає виправданої та обмеженої потреби.
- Сильне логування (запис сесій, якщо ваш ризик це вимагає).
- Мережеві контролі: сервери приймають SSH лише з діапазонів бастіонів/VPN.
- Короткочасний доступ де можливо.
Практичні завдання з командами, виводами та рішеннями (12+)
Це задачі з поля, які ви можете реально виконати на Debian 13. Кожна містить: команду, що означає вивід, і яке рішення робити далі. Використовуйте їх під час ротації, реагування на інцидент або аудиту.
Завдання 1: Підтвердити, що sshd справді використовує для authorized keys
cr0x@server:~$ sudo sshd -T | egrep -i 'authorizedkeys(file|command)|pubkeyauthentication|passwordauthentication'
pubkeyauthentication yes
passwordauthentication no
authorizedkeysfile .ssh/authorized_keys .ssh/authorized_keys2
authorizedkeyscommand none
Значення: Цей хост використовує per-user файли ключів; централізованої команди немає. Паролі вимкнені (добре).
Рішення: Відкликання має торкнутися файлів на диску (або перекласти це в керовану/централізовану модель). Зробіть інвентар шляхів authorized_keys для кожного акаунта.
Завдання 2: Перевірити, що sshd працює з тією конфігурацією, яку ви думаєте
cr0x@server:~$ systemctl status ssh
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; preset: enabled)
Active: active (running) since Mon 2025-12-29 11:02:14 UTC; 3h 18min ago
Docs: man:sshd(8)
man:sshd_config(5)
Main PID: 1023 (sshd)
Tasks: 1 (limit: 18956)
Memory: 5.7M
CPU: 1.421s
CGroup: /system.slice/ssh.service
└─1023 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"
Значення: sshd активний. Командний рядок показує очікуваний бінарник демон.
Рішення: Якщо зміни не застосовуються, ви, ймовірно, змінили не той файл, є проблеми з порядком include або забули зробити reload.
Завдання 3: Перевірити include конфігу і зловити помилки перед reload
cr0x@server:~$ sudo sshd -t
cr0x@server:~$ echo $?
0
Значення: Код виходу 0 означає, що синтаксис конфігу вірний.
Рішення: Продовжуйте з systemctl reload ssh. Якщо код відмінний від нуля — не перезавантажуйте; виправте конфіг перш ніж ризикувати закрити доступ.
Завдання 4: Показати, хто може логінитися (локальні акаунти) і знайти несподіванки
cr0x@server:~$ getent passwd | awk -F: '($3>=1000 && $1!="nobody"){print $1":"$6":"$7}' | head
alice:/home/alice:/bin/bash
bob:/home/bob:/bin/bash
deploy:/srv/deploy:/bin/bash
backup:/var/lib/backup:/usr/sbin/nologin
ci-runner:/var/lib/ci-runner:/bin/bash
Значення: Є інтерактивні користувачі та сервісні акаунти. Деякі акаунти мають нестандартні home.
Рішення: Інвентаризуйте ключі не лише в /home, а й у кастомних директоріях. Також перевірте, чи акаунти з nologin мають ключі і чи повинні вони їх мати.
Завдання 5: Знайти кожен authorized_keys файл на хості (швидко, гучно, ефективно)
cr0x@server:~$ sudo find / -xdev -type f -name authorized_keys -o -name authorized_keys2 2>/dev/null | head
/root/.ssh/authorized_keys
/home/alice/.ssh/authorized_keys
/home/bob/.ssh/authorized_keys
/srv/deploy/.ssh/authorized_keys
Значення: Це ворота ключів на цій системі (з огляду на Завдання 1). Якщо ви бачите несподівані локації — часто саме там «тимчасове» стало постійним.
Рішення: Для ротації потрібно оновити кожен з цих файлів. Для запобігання — наведіть єдине кероване джерело істини.
Завдання 6: Витягти відбитки з authorized_keys і видуплікати по акаунтах
cr0x@server:~$ sudo awk '{print $1" "$2}' /home/alice/.ssh/authorized_keys | ssh-keygen -lf -
256 SHA256:6Oq2j0J3j7cD4Yp8v0Fh7u2i9lXkYxJr3tZx0mQy7xM alice@laptop (ED25519)
Значення: Тепер у вас є стабільний відбиток ключа. Це ідентичність, проти якої ви ротуєте/відкликаєте.
Рішення: Зберіть список відбитків для видалення. Якщо той самий відбиток зустрічається в кількох акаунтах, відкликання має бути координованим або ви пропустите шлях доступу.
Завдання 7: Підтвердити, що підозрілий ключ ще приймається (перевірка на сервері через логи sshd)
cr0x@server:~$ sudo journalctl -u ssh -n 30 --no-pager
Dec 30 09:10:42 server sshd[22144]: Accepted publickey for alice from 10.30.4.18 port 51222 ssh2: ED25519 SHA256:6Oq2j0J3j7cD4Yp8v0Fh7u2i9lXkYxJr3tZx0mQy7xM
Dec 30 09:11:03 server sshd[22190]: Failed publickey for bob from 10.30.4.18 port 51301 ssh2: ED25519 SHA256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Dec 30 09:11:03 server sshd[22190]: Connection closed by authenticating user bob 10.30.4.18 port 51301 [preauth]
Значення: Логи сервера показують, який відбиток було прийнято або відхилено.
Рішення: Якщо «відкликаний» відбиток усе ще приймається — він існує десь в auth-шляху (інший акаунт, інший файл, централізовані ключі або примусовий wrapper-командою).
Завдання 8: Перевірити, чи акаунт заблоковано (швидкий аварійний вимикач)
cr0x@server:~$ sudo passwd -S alice
alice P 2025-12-01 0 99999 7 -1
Значення: Статус P вказує, що акаунт має придатний парольний хеш. Це безпосередньо не вказує на доступ по ключу SSH, але показує, чи може парольна автентифікація спрацювати, якщо увімкнена.
Рішення: Для негайного відключення: заблокуйте акаунт (L) і видаліть ключі. Також підтвердіть, що PasswordAuthentication вимкнено (Завдання 1).
Завдання 9: Заблокувати акаунт і перевірити блокування
cr0x@server:~$ sudo usermod -L alice
cr0x@server:~$ sudo passwd -S alice
alice L 2025-12-01 0 99999 7 -1
Значення: L означає, що пароль заблоковано. SSH по ключу все ще може працювати, якщо ви його не контролюєте через опції sshd або не видалили ключі.
Рішення: На цьому не зупиняйтесь. Видаліть матеріал ключа або вимкніть SSH для акаунта через DenyUsers/Match User правила, якщо потрібне негайне відключення SSH.
Завдання 10: Забезпечити «немає SSH для цього користувача» через Match блок (хірургічно, відновлювано)
cr0x@server:~$ sudo sh -c 'printf "\nMatch User alice\n PasswordAuthentication no\n PubkeyAuthentication no\n KbdInteractiveAuthentication no\n" >> /etc/ssh/sshd_config.d/99-disable-alice.conf'
cr0x@server:~$ sudo sshd -t
cr0x@server:~$ sudo systemctl reload ssh
cr0x@server:~$ sudo sshd -T -C user=alice,host=server,addr=10.30.4.18 | egrep -i 'pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication'
pubkeyauthentication no
passwordauthentication no
kbdinteractiveauthentication no
Значення: Ефективна конфігурація для цього користувача має вимкнену автентифікацію по публічному ключу. Це блокує SSH, навіть якщо ключі ще існують.
Рішення: Використовуйте це як аварійний блок, поки ви шукаєте розподілені ключі. Видаліть Match правило після завершення прибирання.
Завдання 11: Перевірити, що права файлів не змушують sshd ігнорувати ключ
cr0x@server:~$ sudo namei -l /home/alice/.ssh/authorized_keys
f: /home/alice/.ssh/authorized_keys
drwxr-xr-x root root /
drwxr-xr-x root root home
drwxr-xr-x alice alice alice
drwx------ alice alice .ssh
-rw------- alice alice authorized_keys
Значення: Це відповідає звичайним строгим вимогам прав. Якщо ви бачите групові чи світові записи в директоріях або домашніх, sshd може ігнорувати файл (залежно від конфіг).
Рішення: Виправте права перед тим, як звинувачувати ключі. «Ротація ключів не спрацювала» часто насправді означає «sshd відмовився читати файл».
Завдання 12: Тест клієнта з детальними логами SSH (щоб дізнатись правду)
cr0x@server:~$ ssh -vvv -i ~/.ssh/id_ed25519 alice@server
debug1: Offering public key: /home/cr0x/.ssh/id_ed25519 ED25519 SHA256:6Oq2j0J3j7cD4Yp8v0Fh7u2i9lXkYxJr3tZx0mQy7xM explicit
debug1: Server accepts key: /home/cr0x/.ssh/id_ed25519 ED25519 SHA256:6Oq2j0J3j7cD4Yp8v0Fh7u2i9lXkYxJr3tZx0mQy7xM explicit
debug1: Authentication succeeded (publickey).
Welcome to Debian GNU/Linux
Значення: Ви бачите, який ключ пропонувався, чи прийняв його сервер і чи пройшла автентифікація.
Рішення: Якщо клієнт пропонує не той ключ — виправте клієнт (агент, конфіг, identity files). Якщо сервер приймає старий ключ — він усе ще авторизований десь.
Завдання 13: Безпечно видалити конкретний ключ, співставивши тіло ключа, а не коментар
cr0x@server:~$ sudo grep -n 'AAAAC3NzaC1lZDI1NTE5AAAAIFakeKeyBodyGoesHereButLooksRealToHumans' /home/alice/.ssh/authorized_keys
3:ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFakeKeyBodyGoesHereButLooksRealToHumans old-laptop
cr0x@server:~$ sudo sed -i '3d' /home/alice/.ssh/authorized_keys
cr0x@server:~$ sudo tail -n +1 /home/alice/.ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINewKeyBodyLooksDifferent new-laptop
Значення: Ви знайшли точний рядок за тілом ключа і видалили його за номером рядка.
Рішення: Це безпечніше, ніж шукати по коментарю. Після видалення перевірте логін і дивіться логи на предмет несподіваних альтернативних шляхів.
Завдання 14: Виявити дублікати ключів на хості (дешевий детектор розростання)
cr0x@server:~$ sudo find /home /root /srv -xdev -name authorized_keys -type f -print0 2>/dev/null | xargs -0 awk '{print $1" "$2}' | sort | uniq -c | sort -nr | head
4 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDuplicateKeyBodyExample
2 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQAnotherDupExample
Значення: Той самий публічний ключ з’являється кілька разів у різних акаунтах/шляхах.
Рішення: Дублікати ключів майже завжди — проблема управління. Вирішіть, чи це загальний ключ бота (погано, але часто) чи випадкове повторне використання (гірше). У будь-якому випадку — плануйте розділення ідентичностей.
Завдання 15: Підтвердити, що sshd відкине паролі і keyboard-interactive
cr0x@server:~$ sudo sshd -T | egrep -i 'passwordauthentication|kbdinteractiveauthentication|usepam'
passwordauthentication no
kbdinteractiveauthentication no
usepam yes
Значення: Пароль і keyboard-interactive вимкнені, але PAM все ще використовується (часто для налаштування сесії).
Рішення: Хороша база для автентифікації по ключу. Якщо ви увімкнете інтерактивні методи під час усунення проблем, не забудьте знову їх вимкнути — тимчасові виключення швидко стають постійними.
Завдання 16: Помітити і вимкнути agent forwarding на серверах, де він не потрібен
cr0x@server:~$ sudo sshd -T | egrep -i 'allowagentforwarding|allowtcpforwarding|permittty'
allowagentforwarding yes
allowtcpforwarding yes
permittty yes
Значення: Agent forwarding і TCP forwarding дозволені за замовчуванням тут.
Рішення: На продакшн-серверах, особливо тих, що можуть дістатися до інших чутливих систем, розгляньте вимкнення форвардингу або обмеження через Match правила. Форвардинг розширює радіус ураження при скомпрометованій сесії сервера.
Жарт №2: Якщо ви не ротуєте SSH-ключі, вони не «дозрівають як вино». Вони псуються як молоко в серверній.
Три корпоративні історії з практики
Міні-історія 1: Інцидент, спричинений хибним припущенням
Компанія мала політику: «Всі SSH-ключі керуються конфігураційним менеджментом». Усі в це вірили, бо це було правдою для основного флоту додатків. SRE відвернув скомпрометований ключ розробника і видалив його з репозиторію CM. Вони оголосили перемогу, написали пост-інцидентний звіт і пішли далі.
За тиждень аудитор запитав просте питання: «Чи цей ключ ще куди-небудь підключається?» Хтось спробував SSH з карантинної машини (безпечним способом, з дозволами) і зайшов — на машину звітування бази даних. Не головну БД. Тимчасовий reporting host, піднятий на квартал для проєкту роками тому, ніколи не був інтегрований у CM.
Хибне припущення було не технічним, а організаційним. Вони вважали, що покриття інструментів відповідає їхній ментальній моделі. Це було не так. Ключ жив у /root/.ssh/authorized_keys на хості, якого ніхто регулярно не патчить, бо «це не продакшн». Але він мав мережевий доступ до реплік, а це вже достатньо продакшн.
Виправлення не було героїчним. Вони написали джоб, що перелічував сліди authorized key по всіх доступних хостах і порівнював відбитки з дозволеним списком. Перший запуск був ганебним. Другий — дієвим. Третій — рутинним.
Висновок: якщо ви не можете виміряти розміщення ключів, у вас не управління ключами. У вас — надія.
Міні-історія 2: Оптимізація, що відкотилася назад
Платформна команда вирішила швидко централізувати SSH-ключі. Вони зробили AuthorizedKeysCommand, що опитує внутрішній HTTP-сервіс: дай юзернейм — поверни ключі. Гарна ідея, швидко відправлена, аплодисменти на мітингу.
Потім стався перший справжній outage. Сервіс ключів мав часткову відмову: API був вгору, але латентність зросла через проблему в базі даних. SSH-логіни не «падають з помилкою». Вони просто зависають під час автентифікації. Інженери не могли зайти, щоб виправити інцидент, що спричинив латентність. Автоматизація, яка покладалася на SSH, почала повільно і непередбачувано валитися.
Команда оптимізувала під «single source of truth» і забула інженерити на відмовостійкість. Ніякого кешування, ніякого fallback, ніякого circuit breaker, ніякого локального аварійного шляху. Проблему вони перенесли з «розподілені ключі» на «центральна залежність для кожного логіну».
Вони відкотилися, тимчасово відновивши локальні authorized_keys для on-call і break-glass акаунтів, а потім переробили сервіс ключів: кешування на хостах, строгі таймаути і дизайн, що закриває доступ для звичайних користувачів у разі помилок, але відкриває для break-glass в контрольованих умовах (з сигналізаціями).
Висновок: централізація — не безкоштовний обід. Це обмін хаосом, який можна grep-ити, на сервіс, який потрібно експлуатувати як щось важливе — бо це так.
Міні-історія 3: Нудна, але правильна практика, що врятувала день
Фінансово суміжна компанія мала невеликий флот, але одну звичку, яка здавалася надміру консервативною: кожна ротація ключів мала runbook і «перекриття двома ключами». Також вони підтримували невеликий break-glass процес з квартальними тестами. Людям це здавалося повільним. Люди завжди скаржаться на речі, що працюють.
Одного дня вкрали ноутбук з SSH-ключами з машини інженера. Інженер одразу повідомив. Безпека оголосила компрометацію і попросила доказів, що доступ відкликано по всьому продакшену.
On-call дотримувався runbook: визначив відбитки з відомих публічних ключів інженера, заблокував користувача через Match файл на бастіонах за кілька хвилин, а потім натиснув CM-оновлення, яке видалило відбитки з усіх продакшен-хостів. Вікно перекриття не знадобилося; це було жорстке відкликання. Вони верифікували відкликання, пробуючи аутентифікацію з контрольованого середовища і перевіряючи логи sshd на відхилені відбитки.
Аудиторські докази сформувалися самі: тікети змін, diff в CM, логи деплою і системні логи, що показують відхилені спроби. Інцидент залишився малим, бо практика була нудною, задокументованою й відрепетируваною.
Висновок: найбільш ефективні заходи безпеки — ті, які команда може виконати під стресом без імпровізації.
Типові помилки: симптом → корінь проблеми → виправлення
Це повторювані режими відмов, які роблять ротацію ключів проклятою. Більшість прогнозовані. Це хороша новина.
1) Симптом: «Ми видалили ключ, але він все ще входить»
Корінь проблеми: Ключ є в іншому акаунті authorized_keys, іншому шляху через AuthorizedKeysFile, або його отримує AuthorizedKeysCommand. Іноді той самий приватний ключ використовується через agent forwarding.
Виправлення: Ідентифікуйте за відбитком у логах sshd, потім шукайте по флоту тіло/відбиток ключа. Також перевірте бастіони і спільні акаунти. Вимкніть agent forwarding, де не потрібно.
2) Симптом: «Новий ключ не працює на одному сервері, але працює всюди»
Корінь проблеми: Права/власність на ~/.ssh або authorized_keys занадто відкриті, або домашня директорія користувача недоступна з потрібними правами.
Виправлення: Використайте namei -l, щоб перевірити кожний компонент шляху. Відновіть власність і права. Підтвердіть ефективну конфігурацію sshd і поведінку StrictModes.
3) Симптом: «CI деплої почали падати одразу після ротації»
Корінь проблеми: Автоматизація використовувала спільний ключ деплою, який не був ротований, або він збережений в секретному сховищі і не оновлений скрізь. Іноді CI-ранер використовує SSH-агент з кількома ідентичностями і тепер пропонує неправий ключ першим.
Виправлення: Перегляньте логи CI щодо запропонованого відбитка. Зафіксуйте точний ключ з IdentitiesOnly yes і явним IdentityFile на ранері. Ротуйте ботові ключі окремо з поетапним cutover.
4) Симптом: «Після централізації ключів SSH логіни рандомно зависають»
Корінь проблеми: AuthorizedKeysCommand залежить від повільного сервісу. Шлях автентифікації став залежним від мережі і чутливим до латентності.
Виправлення: Додайте кешування, таймаути і обсервабельність. Переконайтесь, що команда падає швидко. Розгляньте локальні кешовані знімки ключів з періодичним оновленням.
5) Симптом: «Люди постійно додають ключі і ніколи їх не видаляють»
Корінь проблеми: Немає власника, немає процесу і немає видимості. Видалення здається ризиковим, бо ніхто не знає, що зламається.
Виправлення: Примусьте управління через CM або центральне сховище. Додайте звіти (ключі на акаунт, вік ключа, останнє використання через логи). Встановіть термін дії або період перевірки.
6) Симптом: «Під час зміни з’явились попередження про ключ хоста»
Корінь проблеми: Ви ротували ключі хоста (або перебудували сервери) без плану розповсюдження known_hosts, або у вас повторне використання DNS/IP викликає невідповідності.
Виправлення: Розділяйте управління ключами хоста від ротації користувацьких ключів. Використовуйте стабільні механізми розповсюдження ключів хоста або обережно оновлюйте known_hosts в автоматизації.
Чеклісти / покроковий план
Це план, що працює, коли ви втомлені, зайняті і оточені системами, яким байдуже до ваших емоцій.
Чекліст A: Контрольована ротація (планована зміна)
- Визначте обсяг: які користувачі, які хости, які акаунти автоматизації.
- Витягніть відбитки старих ключів, що підлягають виведенню з обігу (збережіть їх у тікеті зміни).
- Інвентарізуйте шляхи авторизації:
sshd -T, знайдіть authorized_keys файли, визначте будь-якийAuthorizedKeysCommand. - Розгортайте нові ключі: додайте нові ключі скрізь, де потрібно; поки не видаляйте старі.
- Перевірте доступ: використайте
ssh -vvvдля репрезентативних клієнтів; перевіртеjournalctl -u sshна прийняті відбитки. - Встановіть grace-вікно: повідомте дедлайн; тримайте його коротким.
- Перемикання: видаліть старі відбитки; перезавантажте sshd, якщо змінився конфіг.
- Доведіть відкликання: спробуйте логін зі старим ключем з контрольованого середовища; перевірте логи на відмови.
- Приберіть: видаліть тимчасові Match-блоки, закрийте тікети і очистіть застарілі файли ключів. Оновіть інвентар.
Чекліст B: Аварійне відкликання (підозра на компрометацію)
- Ідентифікуйте відбитки підозрілих ключів (з інвентарю пристроїв співробітників, логів або сховищ ключів).
- Блокуйте швидко в контрольних точках: спочатку бастіони. Використайте
Match UserабоDenyUsersяк невідкладний тимчасовий захід. - Вимкніть видачу якщо ви використовуєте сертифікати; інакше видаліть ключі з центрального сховища/CM.
- Шукайте дублікати: спільні deploy-ключі і скопійовані ключі дуже поширені. Не припускайте єдиного місця.
- Підтвердьте за логами: перевірте відхилені спроби для відбитка.
- Пост-інцидентне прибирання: ротируйте бот-ключі, зменшіть форвардинг, додайте обмеження опцій ключів і закрийте прогалини в інвентарі, які дозволили розростання.
Чекліст C: Базовий набір проти розростання для sshd на Debian 13
- Парольна автентифікація вимкнена, якщо немає сильної причини.
- Централізуйте рішення авторизації (CM, центральна команда ключів або сертифікати).
- Обмежте мережевий доступ для SSH (тільки бастіон/VPN).
- За замовчуванням вимкніть agent/tcp forwarding; дозвольте за роллю через
Match. - Логування достатнє для аудиту (і відправка логів за хост).
- Break-glass доступ мінімальний, контрольований і протестований.
Питання та відповіді
1) Чи потрібно регулярно ротуувати SSH-ключі, навіть без зламу?
Так, але не механічно. Ротуйте при зміні ролей, офбордингу, втраті пристрою і за політикою для ризикових доступів. Якщо ви можете перейти на короткоживучі SSH-сертифікати, ротація стане переважно автоматичною.
2) Який найчистіший спосіб відкликати доступ одного користувача прямо зараз?
Заблокуйте SSH для цього користувача через Match User правило на бастіонах (або прямо на хості якщо треба), потім видаліть їхні ключі з реального джерела авторизації. Верифікуйте за логами і контрольованою спробою входу.
3) Якщо я заблокував Linux-акаунт, чи це блокує вхід по SSH ключу?
Не гарантовано. Блокування акаунта впливає на парольну автентифікацію і іноді на поведінку PAM, але public key auth може і надалі працювати залежно від конфігурації. Розглядайте блок акаунта як вимикач, а не як єдине рішення.
4) Як дізнатися, який ключ використовувався під час входу?
Перевірте логи sshd: рядки успішної publickey автентифікації містять тип ключа й відбиток. На Debian зазвичай найшвидший шлях — journalctl -u ssh.
5) У нас сотні серверів. Чи grep по authorized_keys скрізь — єдиний варіант?
Це «працює сьогодні», але не масштабовано. На рівні флоту використовуйте конфігураційне управління для примусу, централізовану команду authorized keys з кешуванням або — краще — SSH користувацькі сертифікати.
6) Чи складно запускати SSH-сертифікати?
Вони операційно відрізняються, але не обов’язково складніші. Ви міняєте розповсюдження ключів на операції з CA: безпечне підписування, політика, синхронізація часу і робочі процеси видачі. Якщо ви вже керуєте PKI або системами ідентичності — це логічне рішення.
7) Чи варто дозволяти agent forwarding?
За замовчуванням — ні. Дозволяйте лише там, де це суттєво зменшує розповсюдження ключів і де цільові хости — довірені та загартовані. Agent forwarding перетворює скомпрометований сервер на плацдарм для поширення.
8) Який найшвидший спосіб виявити розростання ключів на одному хості?
Запустіть sshd -T, щоб підтвердити механізм автентифікації, потім перелікуйте authorized_keys файли й підрахуйте дублікати тіл/відбитків ключів між ними. Дублікати — перша сигнальна ознака.
9) Чому після «міграції до централізованих ключів» у файлах ще залишаються старі ключі?
Тому що міграції часто часткові. Якщо AuthorizedKeysFile ще ввімкнено і файли існують, sshd може їх і далі враховувати. Визначте один шлях, а потім примусово дотримуйтеся його, включаючи видалення або ігнорування спадкових файлів.
10) Як довести аудиторам, що ключ відкликано?
Збережіть відбиток у записі зміни, покажіть diff/видалення з джерела авторизації і захопіть логи sshd з відхиленими або відсутніми прийняттями після cutover.
Висновок: наступні кроки, що приживаються
Якщо ви винесете одну думку з випадку №13 — нехай це буде: ротація ключів — проблема управління, загорнена в криптографію. Debian 13 дає ті самі гострі інструменти; ваше завдання — користуватися ними послідовно.
Зробіть наступне, в порядку пріоритету:
- Оберіть модель авторизації (керовані локальні файли, централізовані ключі або сертифікати) і перестаньте змішувати їх довільно.
- Побудуйте інвентар за відбитками, щоб відповідати на «хто має доступ» без здогадок.
- Відпрацюйте аварійне відкликання через бастіони і протестовані Match-правила.
- Скоротіть час життя креденшіалів де тільки можна — TTL сертифікатів, жорсткіші опції ключів, менше спільних ключів.
- Вимірюйте розростання: кількість ключів на акаунт, дублікати і ключі, які не видно в логах місяцями.
Зробіть гігієну ключів нудною. Ваш майбутній on-call в нерозумний час буде вдячний — і все ще буде скаржитися, але з меншими відмовами.