Модуль 3.3: Посилення безпеки ядра Linux та операційної системи
Складність:
[СЕРЕДНЯ]— системне адміністрування з акцентом на безпеку.Час на проходження: 40-45 хвилин.
Передумови: Базові навички адміністрування Linux, знання середовища виконання контейнерів.
Що ви зможете зробити
Розділ «Що ви зможете зробити»Цей модуль розглядає посилення безпеки ядра як операційну задачу проєктування, а не як перелік магічних імен sysctl. Наприкінці ви зможете подивитися на робочий вузол Kubernetes 1.35, відокремити налаштування, яких вимагає Kubernetes, від налаштувань, що лише розширюють поверхню атаки, і обґрунтувати точний перелік хостових засобів контролю, які ви б змінили перед виведенням у продакшн.
- Діагностувати налаштування
sysctlнод Kubernetes і пояснити, які значення захищають спільне ядро, не ламаючи мережу Подів. - Спроєктувати мінімальний базовий профіль хостової ОС, який зменшує кількість пакетів, служб, відкритість SSH, ризики файлової системи та відставання у встановленні оновлень.
- Провести аудит конфігурації kubelet, сертифікатів,
/proc,/sysта auditd, щоб виявити ознаки дрейфу в посиленні безпеки хосту. - Оцінити вибір ізоляції середовища виконання контейнерів — наприклад, seccomp, простори імен користувачів, файлові системи лише для читання та засоби контролю підвищення привілеїв.
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Навчальний сценарій: ваш кластер проходить перевірки політик допуску, кожен застосунковий Под має непривілейований контекст безпеки, а мережева команда розгорнула NetworkPolicies на рівні просторів імен. Під час перевірки ноди ви виявляєте, що образ робочого вузла досі запускає служби друку, виявлення мережі та віддаленого виклику процедур, дозволяє SSH за паролем, відкриває повідомлення ядра непривілейованим користувачам і не має встановленого оновлення безпеки ядра. З погляду Kubernetes API застосунки виглядали захищеними, проте сама нода все одно залишає зловмисникам велику поверхню атаки на рівні хосту після будь-якої втечі з контейнера.
Це напруження — серцевина посилення безпеки ядра та операційної системи в Kubernetes. Контейнер — це не крихітна віртуальна машина з власним ядром; це дерево процесів, ізольоване просторами імен Linux, cgroups, можливостями (capabilities), хуками LSM, фільтрами seccomp, параметрами монтування та конфігурацією середовища виконання. Ці шари потужні, але всі вони завершуються тим самим ядром хосту, тож хиба чи неправильна конфігурація нижче за kubelet може вплинути на кожне робоче навантаження, заплановане на ноду.
Іспит CKS не очікує, що ви станете розробником ядра, але він очікує, що ви впізнаватимете, які хостові налаштування мають значення для ноди Kubernetes. Ви маєте зберегти необхідну мережеву поведінку, як-от пересилання IP (IP forwarding), зменшити кількість зайвих локальних інструментів та демонів, обмежити витоки інформації з /proc, /sys та журналів ядра і пов’язати засоби контролю середовища виконання з моделлю спільного ядра. Мета — не нода, яка виглядає захищеною у звичайному сканері; мета — нода, яка коректно виконує Kubernetes, водночас усуваючи небажані шляхи від компрометації контейнера до контролю над хостом.
Проблема спільного ядра
Розділ «Проблема спільного ядра»Найважливіша ментальна модель проста: Под планується через Kubernetes, але його контейнери зрештою стають процесами Linux на ноді. Середовище виконання контейнерів просить у ядра простори імен, cgroups, монтування, можливості та поведінку seccomp, а потім ядро забезпечує дотримання цих меж. Якщо ядро чи хостова ОС відкривають забагато інформації, запускають вразливі служби або залишають небезпечні права доступу, Kubernetes не може повністю це компенсувати згори.
┌─────────────────────────────────────────────────────────────┐│ CONTAINER KERNEL SHARING │├─────────────────────────────────────────────────────────────┤│ ││ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││ │ Container A │ │ Container B │ │ Container C │ ││ │ (nginx) │ │ (redis) │ │ (attacker?) │ ││ └─────┬───────┘ └─────┬───────┘ └─────┬───────┘ ││ │ │ │ ││ └────────────────┼────────────────┘ ││ │ ││ ▼ ││ ┌──────────────────────────────────────────────────────┐ ││ │ HOST KERNEL │ ││ │ │ ││ │ All containers use the SAME kernel │ ││ │ Kernel exploit = compromise ALL containers │ ││ │ Privilege escalation = host access │ ││ │ │ ││ └──────────────────────────────────────────────────────┘ ││ │ ││ ▼ ││ ┌──────────────────────────────────────────────────────┐ ││ │ HARDWARE │ ││ └──────────────────────────────────────────────────────┘ ││ │└─────────────────────────────────────────────────────────────┘Ця схема — причина, чому посилення безпеки хосту належить до навчальної програми з безпеки Kubernetes. Контейнери A та B можуть бути звичайними службами, тоді як контейнер C може бути скомпрометованим робочим навантаженням, що отримало виконання коду. Якщо контейнер C може дізнатися адреси ядра, прочитати деталі процесів хосту, завантажити ланцюг атаки на ядро або зловжити зайвим демоном ноди, радіус ураження (blast radius) уже не обмежується цим Подом.
Віртуальні машини проводять цю межу інакше. ВМ зазвичай несе власне гостьове ядро, тож вада гостьового ядра не стає автоматично вадою ядра хосту, хоча втечі з гіпервізора залишаються можливими. Контейнери обмінюють цю міцнішу межу ядра на швидкість, щільність та операційну простоту, а це означає, що ви маєте посилити спільне ядро та хостову ОС навколо нього.
Посилення безпеки ядра також має проблему спрямованості. Об’єкти Kubernetes, як-от допуск PodSecurity, securityContext та NetworkPolicy, видимі через API-сервер, тож команди часто переглядають їх першими. Хостові засоби контролю розподілені між системними пакетами, службами, файлами sysctl, шляхами kubelet, конфігурацією середовища виконання, параметрами монтування та правилами аудиту, тож дрейф може приховуватися, поки образ ноди не перезберуть або інцидент не змусить до перевірки.
Зупиніться та спрогнозуйте: якщо зловмисник вирветься з одного непривілейованого контейнера й опиниться на ноді як користувач із низькими привілеями, яка хостова інформація допоможе йому обрати наступний шлях експлуатації? Подумайте про версію ядра, завантажені модулі, переліки процесів, облікові дані kubelet, придатні для запису файлові системи, локальні компілятори та мережеві демони, перш ніж дивитися на команди далі в модулі.
Практична послідовність посилення йде тим самим шляхом, яким користувався б зловмисник. Спершу зменште те, що встановлено й запущено, щоб було менше локальних інструментів та вразливих служб. Далі налаштуйте параметри ядра так, щоб поширені прийоми розвідки та мережеві трюки зазнавали невдачі. Потім захистіть чутливі хостові файли та псевдофайлові системи, посиліть ізоляцію середовища виконання й залиште достатньо доказів аудиту, щоб довести, що нода залишалася в цьому стані.
Одна тонкість має значення для іспитових питань та реальних операцій: не кожне загальне правило посилення Linux належить незмінним на ноду Kubernetes. Звичайний сервер може вимикати пересилання IP, але робочому вузлу пересилання зазвичай потрібне для трафіку Подів та Сервісів. Зріле судження полягає у вмінні розрізняти, коли налаштування справді небезпечне, коли воно потрібне платформі, і які компенсаційні засоби контролю роблять необхідний виняток прийнятним.
Модель спільного ядра також пояснює, чому межі контейнера зроблені з кількох менших засобів контролю, а не з одного великого вмикача. Простори імен обмежують те, що може бачити процес, cgroups обмежують те, що він може споживати, можливості (capabilities) ділять root-подібну владу на вужчі привілеї, фільтри seccomp блокують вибрані системні виклики, а модулі безпеки Linux (LSM) додають рішення політики навколо файлів та операцій. Слабкість в одному шарі не завжди означає негайний контроль над хостом, але дає зловмисникам більше простору, щоб поєднати помилки.
Проєктування пулів нод — ще одна частина посилення безпеки ядра, бо планувальник вирішує, які робочі навантаження ділять одне ядро. Якщо високоризикові робочі навантаження, привілейовані системні агенти та звичайні застосункові Поди працюють в одному пулі, вада хосту має ширші операційні наслідки. Taint’и, толерантності, мітки нод, RuntimeClass та політики допуску дозволяють відокремити робочі навантаження, яким потрібні додаткові привілеї, від навантажень, що мають залишатися на суворішому базовому профілі.
Моделювання загроз тримає модуль практичним. Ви не намагаєтеся зупинити зловмисника, який уже має необмежений root на фізичному хості та повний доступ до площини управління вашої хмари. Ви зменшуєте кількість кроків між компрометацією застосунку та компрометацією ноди, обмежуєте корисну розвідку й робите дрейф ноди видимим, перш ніж він перетвориться на легкий шлях по кластеру після втечі.
Спроєктуйте мінімальний, придатний для оновлень базовий профіль хостової ОС
Розділ «Спроєктуйте мінімальний, придатний для оновлень базовий профіль хостової ОС»Посилення безпеки хосту починається ще до того, як запуститься kubelet. Робочий вузол має бути схожим радше на запломбований пристрій, ніж на сервер загального призначення з входом за логіном, адже кожен установлений пакет стає тягарем для обслуговування, а кожен активний демон — можливою точкою входу. Мінімальні образи на кшталт Talos, Flatcar, Bottlerocket та інших оптимізованих для контейнерів операційних систем втілюють цю ідею, прибираючи інтерактивні шляхи адміністрування й зосереджуючись на компонентах, потрібних для запуску контейнерів.
Мінімальний не означає загадковий. Ноді Kubernetes усе ще потрібні середовище виконання контейнерів, kubelet, підтримка CNI, синхронізація часу, агенти логування чи моніторингу та той канал управління хостом, який схвалює ваша організація. Чого їй не повинно бути потрібно, так це настільного програмного забезпечення, друку, Bluetooth, мовних інструментаріїв, офісних пакетів, незапланованих оболонок для кожного користувача чи служб виявлення мережі, які не мають жодної ролі в плануванні Подів.
Перший прохід аудиту навмисно нудний: підрахуйте встановлені пакети, визначте очевидне ненодове програмне забезпечення та переконайтеся, що власник образу може пояснити кожну категорію, яка залишається. Кількість пакетів сама по собі не є оцінкою безпеки, бо дистрибутиви по-різному пакують компоненти, але раптовий стрибок кількості пакетів в одному пулі нод — корисний сигнал дрейфу. Сприймайте цю кількість як пожежну сигналізацію, а не як остаточний діагноз.
# List installed packagesdpkg -l | wc -l # Debian/Ubunturpm -qa | wc -l # RHEL/CentOS
# Remove unnecessary packagessudo apt remove -y --purge $(dpkg -l | grep -E 'games|office' | awk '{print $2}')
# Kubernetes nodes should have minimal software:# - Container runtime (containerd, CRI-O)# - kubelet# - kube-proxy (if not running as pod)# - Networking tools# - Monitoring agentsБудьте обережні з видаленням пакетів на робочій ноді. Безпечний продакшн-патерн — виправити образ ноди, розгорнути замінний пул, виконати cordon і drain старих нод і дати планувальнику перенести робочі навантаження. Аварійне очищення наявної ноди може бути доречним під час лабораторної роботи чи локалізованого інциденту, але перезбірка з відомого образу дає вам повторюваний засіб контролю, який переживе перезавантаження, автомасштабування та ремонт ноди.
Запущені служби заслуговують на таке саме ставлення, що й пакети, але з суворішою перевіркою операційних залежностей. cups, avahi-daemon, bluetooth та подібні служби — легкі приклади, бо робочий вузол Kubernetes не має жодної причини рекламувати принтери, брати участь у локальному виявленні чи відкривати бездротові інтерфейси. Інші служби можуть бути вендорськими агентами, детекторами проблем нод, плагінами сховища чи мережевими компонентами, тож підтвердьте власника, перш ніж щось зупиняти на продакшн-інфраструктурі.
# List running servicessystemctl list-units --type=service --state=running
# Disable unnecessary servicessudo systemctl disable --now cups # Printingsudo systemctl disable --now avahi-daemon # mDNSsudo systemctl disable --now bluetooth # Bluetooth
# Essential services to keep:# - containerd or docker# - kubelet# - SSH (for management)# - NTP/chrony (time sync)Найбезпечніший порядок вимкнення оборотний та виміряний. Зафіксуйте поточний перелік служб, зупиніть одного кандидата, переконайтеся, що kubelet та середовище виконання залишаються справними, виконайте простий тест планування Пода і лише потім вимкніть службу остаточно. Якщо ваша організація використовує незмінні ноди, закодуйте зміну в конфігурації збірки образу, замість того щоб вважати systemctl disable довгостроковим виправленням.
Керування оновленнями — друга половина базового профілю. Посилення безпеки ядра та ОС стосується не лише безпечних типових налаштувань; воно також стосується закриття відомих вразливостей, перш ніж вони стануть звичними шляхами експлуатації. Пул нод, який неможливо оновити через надмірну крихкість, не є посиленим, навіть якщо його поточний файл sysctl виглядає охайно.
# Check for security updates (Ubuntu)sudo apt updatesudo apt list --upgradable | grep -i security
# Apply security updates onlysudo unattended-upgrades
# Check kernel versionuname -r
# Check for known kernel CVEs# https://www.kernel.org/Автоматичні оновлення вимагають політики, а не просто пакета. На серверах у стилі «улюбленців» (pets) автоматичні оновлення можна налаштувати на встановлення на місці та перезавантаження під час вікон обслуговування. На оптимізованих для контейнерів чи автомасштабованих пулах робочих нод безпечнішим патерном часто є перезбірка образу, заміна ноди та drain із урахуванням бюджету порушень роботи Подів (Pod disruption budget), бо це уникає накопичення разового стану на довговічних машинах.
Посилення SSH належить до того самого базового профілю, бо аварійний доступ до оболонки потужний і часто забувається. Якщо SSH існує, вхід root має бути вимкнений, автентифікація за паролем має бути вимкнена, перелік дозволених користувачів має бути вузьким, а доступ — логуватися. Якщо платформа підтримує модель без SSH, надавайте перевагу контрольованому процесу «розбий скло» (break-glass) та нативному для Kubernetes налагодженню для рутинного дослідження застосунків.
PermitRootLogin noPasswordAuthentication noAllowUsers admin# Restart SSHsudo systemctl restart sshdПрибирання облікових записів користувачів менш ефектне, ніж нова функція середовища виконання, але часто виявляє дрейф. Старі локальні облікові записи, спільні аварійні користувачі та неактивні адміністративні облікові записи створюють шляхи в обхід вашого постачальника ідентифікації та моделі аудиту. Блокування облікового запису перед видаленням дає безпечніший відкат під час розслідування, тоді як видалення на рівні образу не дає тому самому обліковому запису знову з’явитися під час наступної заміни ноди.
# List users that can logingrep -v '/nologin\|/false' /etc/passwd
# Lock unnecessary accountssudo usermod -L olduser
# Remove usersudo userdel -r unnecessaryuserПерш ніж виконувати команди видалення в реальному середовищі, запитайте, який робочий процес зламається, якщо нода більше не зможе приймати інтерактивний вхід. Відповідь має вказувати на свідомі заміни: kubectl debug для усунення проблем робочих навантажень, серійну консоль чи хмарний session manager для доступу «розбий скло», конвеєри образів нод для постійних змін та централізовані журнали для доказів. Якщо ніхто не може відповісти, команда покладається на неформальний доступ, а не на посилені операції.
Походження образу належить до базового профілю, бо мінімальний образ, зібраний із неясних вихідних даних, усе одно є слабким фундаментом. Образ ноди повинен мати відоме джерело, повторювані кроки збірки, записані версії пакетів та історію оновлень, яку можуть перевірити ревізори безпеки. Це не вимагає важкого процесу для кожного лабораторного кластера, але продакшн-пули робочих нод не повинні залежати від одноразово вручну налаштованої машини, яку ніхто не може відтворити.
Менеджери пакетів створюють ще один операційний вибір. Деякі оптимізовані для контейнерів системи уникають традиційного менеджера пакетів на ноді, що зменшує ймовірність того, що оператор установить інструменти під час усунення проблем і забуде їх видалити. Дистрибутиви загального призначення все ще можна посилити, але команді потрібні засоби контролю навколо встановлення пакетів, довіри до репозиторіїв та виявлення післяустановного дрейфу, щоб нода поступово не перетворилася на сервер-«комбайн».
Перезавантаження — це частина оновлень, а не неприємний виняток із безперервної роботи. Виправлення ядра часто вимагають перезавантаження чи заміни ноди, перш ніж зміниться запущене ядро, тож кластер має витримувати планову ротацію. Бюджети порушень роботи Подів, кілька реплік, надлишкова потужність, розподіл за топологією та автоматизація drain — це не щось окреме від посилення ядра; це механізми, які дозволяють застосовувати посилення без створення збою сервісу.
Планування відкату не менш важливе, ніж планування розгортання. Якщо оновлення ядра ламає драйвер сховища, модуль CNI чи агент моніторингу, операторам потрібен перевірений спосіб зупинити розгортання та повернутися до попереднього образу. Цей відкат має зберегти слід розслідування безпеки, бо сліпий відкат може приховати, чи проблема була в поганому пакеті, несумісному драйвері або недокументованій залежності в пулі нод.
Налаштуйте параметри sysctl для спільного ядра
Розділ «Налаштуйте параметри sysctl для спільного ядра»Налаштування sysctl — це регулятори ядра під час виконання, відкриті через /proc/sys і збережені через файли в локаціях на кшталт /etc/sysctl.d/. Вони привабливі, бо один рядок може змінити реальну поведінку ядра, але водночас ризиковані, бо загальний базовий профіль посилення може конфліктувати з мережею Kubernetes. Ви маєте оцінювати кожне налаштування з погляду того, що воно блокує, чого вимагає Kubernetes і як ви перевірятимете ефект.
Перша група зменшує мережеві зловживання, яких не повинно бути потрібно на робочому вузлі. ICMP-перенаправлення (redirects) та маршрутизація від джерела (source routing) — це старі механізми, які можуть допомогти перенаправити трафік у спосіб, якому сучасний кластер не повинен довіряти. SYN-cookies захищають від певного тиску SYN-флуду, логування «марсіанських» пакетів (martian logging) записує підозрілі пакети, а придушення широкомовного ping прибирає галасливу поведінку підсилення (amplification).
# View current settingssysctl -a | grep -E "net.ipv4|kernel" | head -20Додайте посилені значення до керованого файлу sysctl, а не вставляйте рядки конфігурації безпосередньо в командний рядок оболонки.
# Disable IP forwarding if not needed (kubelets need it!)# net.ipv4.ip_forward = 0 # Don't disable on K8s nodes!
# Ignore ICMP redirectsnet.ipv4.conf.all.accept_redirects = 0net.ipv4.conf.default.accept_redirects = 0net.ipv4.conf.all.send_redirects = 0
# Enable SYN flood protectionnet.ipv4.tcp_syncookies = 1
# Log suspicious packetsnet.ipv4.conf.all.log_martians = 1
# Ignore broadcast pingnet.ipv4.icmp_echo_ignore_broadcasts = 1
# Disable source routingnet.ipv4.conf.all.accept_source_route = 0
# Enable ASLRkernel.randomize_va_space = 2
# Restrict dmesg accesskernel.dmesg_restrict = 1
# Restrict kernel pointerskernel.kptr_restrict = 1# Apply settingssudo sysctl -p /etc/sysctl.d/99-kubernetes-security.confНалаштування ядра в цьому файлі захищають не всі ту саму фазу атаки. kernel.randomize_va_space = 2 вмикає повну рандомізацію розташування адресного простору для користувацьких процесів, роблячи експлуатацію пошкодження пам’яті менш передбачуваною. kernel.dmesg_restrict = 1 блокує читання деталей кільцевого буфера ядра непривілейованими користувачами, тоді як kernel.kptr_restrict = 1 чи суворіше значення зменшує розкриття адрес вказівників ядра, які можуть полегшити експлуатацію.
Мережеві sysctl потребують особливої уваги, бо мережа Kubernetes навмисно використовує пересилання. Трафік Подів може перетинати пари veth, мости, оверлейні інтерфейси та основний інтерфейс ноди залежно від CNI. Якщо загальне правило відповідності каже, що кожен хост Linux має вимкнути пересилання, його сліпе застосування може зламати взаємодію Подів між нодами та маршрутизацію Сервісів, навіть якщо нода виглядає безпечнішою для сканера.
# Required for Kubernetes networkingnet.ipv4.ip_forward = 1net.bridge.bridge-nf-call-iptables = 1net.bridge.bridge-nf-call-ip6tables = 1
# For pod networkingnet.ipv4.conf.all.forwarding = 1
# Connection tracking for servicesnet.netfilter.nf_conntrack_max = 131072Зупиніться та спрогнозуйте: ви встановлюєте net.ipv4.ip_forward = 0 на робочому вузлі Kubernetes, щоб задовольнити загальний чек-лист посилення сервера. Який шлях трафіку зламається першим, і які докази ви б зібрали, щоб довести, що Kubernetes вимагає пересилання, водночас усе ще відхиляючи маршрутизацію від джерела та перенаправлення?
Відповідь залежить від CNI, але міркування стабільне. Пакети мають рухатися між інтерфейсами Подів та іншими мережевими інтерфейсами, і нода бере участь у пересиланні цих пакетів за правилами, встановленими kube-proxy, CNI чи площиною даних eBPF. Ви можете залишити пересилання ввімкненим, водночас вимикаючи перенаправлення, маршрутизацію від джерела та інші види поведінки, які дозволяють недовіреним хостам впливати на рішення маршрутизації.
Сприймайте файли sysctl як артефакти конфігурації, що потребують перегляду та власника. Рукописна зміна, зроблена під час інциденту, може зникнути після перезавантаження, якщо її застосували лише через sysctl -w, а оновлення хмарного образу може перезаписати файл, якщо конвеєр образів не є джерелом істини. Тривкий патерн — керувати цими налаштуваннями через образ ноди, конфігурацію машини чи привілейований механізм початкового завантаження ноди, який схвалює ваша команда безпеки.
У Linux часто існують форми all, default та специфічні для інтерфейсу форми того самого мережевого налаштування, і ця різниця має значення. all може впливати на наявні інтерфейси, default впливає на інтерфейси, створені пізніше, а значення для конкретного інтерфейсу все одно може здивувати вас, коли CNI створює пристрої моста, veth, тунелю чи пов’язані з eBPF. Коли налаштування виглядає правильним в одному місці, але поведінка не збігається, перевіряйте значення для кожного інтерфейса, а не припускайте, що перемогло глобальне значення.
Kubernetes також відкриває обмежену поверхню sysctl через контекст безпеки Пода, але це не те саме, що посилення безпеки ядра хосту. sysctl із простором імен можуть бути безпечними для Пода, бо вони впливають лише на простір імен цього Пода, тоді як небезпечні sysctl можуть впливати на ноду чи інші робочі навантаження й вимагають явного дозволу kubelet. На посиленому кластері ви маєте скептично ставитися до allowedUnsafeSysctls, якщо немає вузької причини на рівні робочого навантаження та виділеної межі ноди.
Відстеження з’єднань (connection tracking) — добрий приклад налаштування, яке може бути водночас пов’язаним із доступністю та значущим для безпеки. Надто низьке значення може відкидати легітимний трафік Сервісів під навантаженням, тоді як необмежене чи погано зрозуміле значення може приховати ризик вичерпання. Правильне налаштування залежить від розміру ноди, патернів з’єднань робочого навантаження, поведінки kube-proxy чи площини даних eBPF та спостережуваності, яку ви маєте щодо тиску на conntrack.
Валідація має містити негативні очікування. Якщо kernel.dmesg_restrict увімкнено, непривілейований користувач повинен зазнати невдачі під час читання повідомлень ядра; якщо перенаправлення вимкнені, нода не повинна приймати вплив на маршрут на основі перенаправлень; якщо пересилання ввімкнене для Kubernetes, звичайний трафік робочого навантаження все одно має проходити. Перевірки посилення стають переконливішими, коли вони показують і те, що все ще працює, і те, що навмисно заблоковано.
Іспит CKS схильний перевіряти впізнавання та діагностику радше, ніж довгу теорію ядра. Вас можуть попросити перевірити поточні значення, застосувати невеликий файл посилення чи визначити, чому «безпечна» зміна зламала кластер. Правильна звичка — спершу прочитати поточне значення, застосувати один добре окреслений файл, перевірити значення після цього й пояснити будь-який потрібний Kubernetes виняток, а не приховувати його.
# Check sysctl settingssysctl net.ipv4.ip_forwardsysctl kernel.randomize_va_space
# Check for unnecessary servicessystemctl list-units --type=service --state=running | wc -l
# Check SSH configurationgrep -E "PermitRootLogin|PasswordAuthentication" /etc/ssh/sshd_configПопередня перевірка навмисно невелика, бо іспитовий термінал винагороджує точне дослідження. net.ipv4.ip_forward каже вам, чи доступне базове пересилання, kernel.randomize_va_space підтверджує поведінку ASLR, кількість служб дає швидкий сигнал про дрейф ноди, а grep по SSH перевіряє два цінні засоби контролю доступу. Звідти ви можете перевірити точний файл, який володіє несподіваним значенням.
# Create hardening configsudo tee /etc/sysctl.d/99-cks-hardening.conf << 'EOF'kernel.dmesg_restrict = 1kernel.kptr_restrict = 2net.ipv4.conf.all.accept_redirects = 0net.ipv4.conf.default.accept_redirects = 0EOF
# Applysudo sysctl -p /etc/sysctl.d/99-cks-hardening.conf
# Verifysysctl kernel.dmesg_restrictКоли ви встановлюєте kernel.kptr_restrict = 2, ви обираєте суворішу позицію, ніж попереднє прикладне значення 1. Це може бути доречним для продакшн-нод, де інструменти спостережуваності не потребують нередагованих вказівників ядра з непривілейованих контекстів. Якщо діагностичний інструмент ламається, виправленням має бути вузько авторизований шлях налагодження, а не постійне послаблення на кожному робочому вузлі.
Захистіть хостові файли, /proc, /sys та межі монтування
Розділ «Захистіть хостові файли, /proc, /sys та межі монтування»Ядро Linux відкриває величезні обсяги системної інформації через псевдофайлові системи на кшталт /proc та /sys. Ця видимість корисна для адміністраторів та агентів моніторингу, але вона також може допомогти зловмисникам перелічити процеси, модулі ядра, командні рядки, інформацію про пристрої та стан під час виконання. Тому посилення безпеки хосту охоплює і те, що звичайні користувачі можуть бачити на ноді, і те, що контейнерам дозволено бачити через їхні монтування.
# Restrict access to process information# In /etc/fstab or mount options:proc /proc proc defaults,hidepid=2 0 0
# hidepid options:# 0 = default (all users can see all processes)# 1 = users can see their own processes only# 2 = users can't see other users' processes
# For containers, Kubernetes manages these mounts# But host should restrict accessПараметр hidepid — це засіб контролю на рівні хосту, тож не плутайте його з поведінкою простору імен процесів на рівні Пода. Kubernetes може вирішувати, чи Под спільно використовує простір імен процесів, а середовище виконання створює специфічні для контейнера представлення, але хосту все одно потрібна політика для локальних користувачів та агентів ноди. Якщо непривілейований локальний обліковий запис може переглядати кожен процес хосту, втеча з контейнера отримує легшу мапу облікових даних, командних рядків та запущених служб.
/sys має інший відтінок ризику, бо він відкриває інтерфейси ядра та пристроїв, а не звичайні метадані процесів. Багатьом легітимним компонентам ноди потрібні його частини, особливо агентам, пов’язаним зі сховищем, мережею та апаратним забезпеченням. Питання посилення не в тому, чи /sys існує; питання в тому, чи отримують контейнери привілейовані хостові монтування або широкий доступ на запис, який дозволяє їм впливати на поведінку ядра чи пристроїв.
Чутливі файли Kubernetes заслуговують на явні перевірки прав доступу. Конфігурація kubelet, клієнтські облікові дані kubelet, згенеровані kubeadm сертифікати та приватні ключі — це цінні файли, бо вони можуть дозволити зловмиснику автентифікуватися на API-сервері чи видавати себе за компоненти ноди. Обмежувальні права доступу не виправлять викрадену root-оболонку, але вони зменшують випадкове розкриття непривілейованим користувачам та погано ізольованим процесам.
# Secure kubelet filessudo chmod 600 /var/lib/kubelet/config.yamlsudo chmod 600 /etc/kubernetes/kubelet.confsudo chown root:root /var/lib/kubelet/config.yaml
# Secure certificatessudo chmod 600 /etc/kubernetes/pki/*.keysudo chmod 644 /etc/kubernetes/pki/*.crtРізниця між приватними ключами та сертифікатами має значення. Приватні ключі мають бути доступними для читання лише root або конкретному сервісному обліковому запису, якому вони потрібні, бо володіння ключем може уможливити видавання себе за іншого. Сертифікати публічні за задумом, тож права лише для читання зазвичай прийнятні, але широкі права на запис для будь-якого з цих типів файлів — це серйозна проблема цілісності.
# Fix kubelet config permissionssudo chmod 600 /var/lib/kubelet/config.yamlsudo chown root:root /var/lib/kubelet/config.yaml
# Verifyls -la /var/lib/kubelet/config.yamlПараметри монтування файлової системи додають ще один шар захисту після того, як процес отримує певний доступ на запис. nodev запобігає інтерпретації файлів пристроїв на цій файловій системі, nosuid запобігає наданню привілеїв бітами setuid, а noexec запобігає прямому виконанню зі шляхів, які мають лише зберігати дані чи журнали. Ці засоби контролю не є ідеальними стінами, що неможливо обійти, але вони змушують зловмисників працювати важче й усувають поширені короткі шляхи.
# /etc/fstab entries with security options
# Separate partitions for:# /var/lib/containerd - Container data# /var/log - Logs# /tmp - Temporary files
# Example secure mount options:/dev/sda3 /var/lib/containerd ext4 defaults,nodev,nosuid 0 2/dev/sda4 /tmp ext4 defaults,nodev,nosuid,noexec 0 2/dev/sda5 /var/log ext4 defaults,nodev,nosuid,noexec 0 2
# Options:# nodev - No device files# nosuid - No setuid executables# noexec - No executionВибір монтування має зважати на реальність робочих навантажень. Застосування noexec до /tmp на хості часто є розумним, але застосування його до шляху, де середовище виконання чи плагін сховища очікує виконувати допоміжні бінарні файли, може зламати роботу ноди. Це рішення належить до тестування образу ноди, а не до ручної зміни поза робочим часом на живому пулі.
Кореневі файлові системи лише для читання — найсильніша версія цієї ідеї. У незмінній інфраструктурі образ ноди замінюється, а не модифікується, придатний для запису стан ізольований, а конфігурація надходить із контрольованого конвеєра. Ця модель різко зменшує дрейф, але вона вимагає хорошого операційного інструментарію, бо стара звичка «зайти через SSH та відредагувати файл» більше не працює.
# For immutable infrastructure:# Mount root as read-only, use overlay for writes
# This is often handled by the OS distribution# (CoreOS, Flatcar, Talos, etc.)Перш ніж це запускати, який вивід ви очікуєте від ls -la /var/lib/kubelet/config.yaml на посиленій ноді в стилі kubeadm? Корисна відповідь називає і власника, і права доступу: файлом має володіти root, звичайні користувачі не повинні мати змоги читати його, а будь-які несподівані права групи чи всіх (world) мають відправити вас до скриптів збірки образу чи початкового завантаження, які створили цей дрейф.
Томи HostPath — це місце, де посилення безпеки файлів та політика Kubernetes зустрічаються безпосередньо. Под, який монтує /var/lib/kubelet, /etc/kubernetes, /var/run чи широкі хостові шляхи, може обійти багато припущень, які ви зробили щодо ізоляції контейнерів. Привілейованим DaemonSet’ам іноді потрібен доступ до хосту для мережі, сховища чи моніторингу, але вони мають жити у строго контрольованих просторах імен із переглянутими маніфестами, виділеними сервісними акаунтами та правилами розміщення на нодах.
Плагіни пристроїв та апаратні агенти заслуговують на подібну прискіпливість. Інтеграції GPU, сховища та мережі можуть легітимно відкривати пристрої чи хостові шляхи, проте вони також розширюють те, до чого може дотягнутися скомпрометований Под. Зрілий хід — не заборонити кожен плагін; це ізолювати ноди, яким він потрібен, переглянути потрібні їм привілеї й уникати планування звичайних застосункових навантажень на той самий високопривілейований пул без причини.
Облікові дані kubelet пов’язують посилення безпеки ноди з авторизацією кластера. Викрадені клієнтські облікові дані kubelet можуть не надати необмеженої влади cluster-admin, але вони все одно можуть розкрити операції ноди та робочих навантажень, що допоможуть зловмиснику здійснити поворот (pivot). Права доступу до файлів, ротація сертифікатів, поведінка авторизатора Node та допуск NodeRestriction — це окремі засоби контролю, що працюють разом, тож аудит хосту має зазначати і локальне розкриття файлів, і права доступу в API.
Оцініть ізоляцію середовища виконання та докази аудиту
Розділ «Оцініть ізоляцію середовища виконання та докази аудиту»Посилення безпеки середовища виконання контейнерів — це місце, де хостові засоби контролю зустрічаються із засобами контролю Пода. Середовище виконання обирає, як створювати контейнери, який профіль seccomp застосовується за замовчуванням, як cgroups інтегруються з systemd і чи доступна підтримка простору імен користувачів або альтернативного середовища виконання. Kubernetes 1.35 усе ще залежить від цього нижчого шару, тож чистий маніфест Пода не може врятувати середовище виконання, налаштоване зі слабкими типовими значеннями.
[plugins."io.containerd.grpc.v1.cri"] # Disable privileged containers (if possible) # Note: Some system pods need privileges
[plugins."io.containerd.grpc.v1.cri".containerd] # Use native (not kata) for performance default_runtime_name = "runc"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] # Use systemd cgroups SystemdCgroup = trueЦей фрагмент containerd зберігає поширений шлях runc, водночас показуючи, де живе вибір середовища виконання. SystemdCgroup = true узгоджує середовище виконання з керованими systemd cgroups, що є очікуваною позицією для багатьох дистрибутивів Kubernetes. Це не перемикач seccomp. Навчайте seccomp на рівні Пода через securityContext.seccompProfile.type: RuntimeDefault, а на кластерах, які навмисно встановлюють типове значення для кожного навантаження, перевіряйте поведінку kubelet --seccomp-default, а не припускайте, що налаштування cgroup відфільтрувало системні виклики.
Деякі середовища досі використовують Docker Engine для сусідніх хостів збірки, тож ті самі ідеї посилення з’являються в конфігурації Docker, навіть коли ноди Kubernetes працюють на containerd. Перевідображення простору імен користувачів (user namespace remapping) може зробити так, що root контейнера відображатиметься на менш привілейовану ідентичність хосту, no-new-privileges блокує підвищення привілеїв під час exec, а профілі seccomp обмежують доступ до системних викликів. Налаштування міжконтейнерної взаємодії та live restore стають додатковими операційними рішеннями.
{ "userns-remap": "default", "no-new-privileges": true, "seccomp-profile": "/path/to/seccomp-profile.json", "icc": false, "live-restore": true}Ізоляція середовища виконання також видима з маніфестів Kubernetes. Под, який працює як непривілейований (non-root), скидає можливості, запобігає підвищенню привілеїв, використовує типовий профіль seccomp середовища виконання та монтує кореневу файлову систему лише для читання, дає ядру менше небезпечних операцій для опосередкування. Ці засоби контролю не є замінниками посилення безпеки хосту; вони зменшують імовірність того, що скомпрометований застосунок досягне межі хосту з достатньою владою, щоб її експлуатувати.
Стара звичка залишати інструменти налагодження постійно встановленими на ноді конфліктує з посиленням середовища виконання. Kubernetes тепер дає вам кращі інструменти, зокрема ефемерні контейнери налагодження та робочі процеси налагодження нод, тож ви можете досліджувати, не тримаючи компілятори, сканери та утиліти оболонки на кожному робочому вузлі назавжди. Ця різниця має значення, бо інструмент, який допомагає адміністратору після входу, може також допомогти зловмиснику після втечі.
Докази аудиту замикають цикл. Посилення без аудиту дає вам бажаний стан, але мало доказів того, що він залишався правдивим, тоді як аудит без посилення дає детальні записи про відворотне розкриття. Корисна золота середина — моніторити цінні бінарні файли середовища виконання, каталоги конфігурації, шляхи сховища контейнерів, конфігурацію kubelet та локації сертифікатів Kubernetes на зміни, які мають бути рідкісними. Починайте зі шляхів, які існують на ноді; наприклад, ноди kind, що працюють на containerd, відкривають бінарний файл середовища виконання за шляхом /usr/local/bin/containerd, тож не припускайте специфічної для дистрибутива локації бінарного файлу.
# Install auditdsudo apt install -y auditd
# Configure containerd-first audit rulessudo install -m 0640 /dev/null /etc/audit/rules.d/container-runtime.rulesfor rule in \ "containerd:/usr/local/bin/containerd" \ "containerd-storage:/var/lib/containerd" \ "containerd-config:/etc/containerd" \ "kubernetes:/etc/kubernetes" \ "kubelet:/var/lib/kubelet"do key="${rule%%:*}" path="${rule#*:}" if sudo test -e "$path"; then printf -- "-w %s -p wa -k %s\n" "$path" "$key" | sudo tee -a /etc/audit/rules.d/container-runtime.rules >/dev/null else echo "Skipping missing audit path: $path" fidone
# Legacy Docker Engine watches belong only on nodes where these paths exist.# Add dockerd, Docker config, and Docker storage watches after test -e confirms them.
# Apply rulessudo augenrules --loadЦі правила аудиту навмисно зосереджені на доказах змін, а не на логуванні кожного системного виклику, зробленого кожним контейнером. Надмірний обсяг аудиту може приховати сигнал, який вам потрібен, вичерпати диск і змусити тих, хто реагує, ігнорувати систему. Хороший дизайн аудиту запитує, які зміни файлу чи бінарного файлу здивували б вас на незмінній чи строго керованій ноді, а потім записує ці події з ключами, що роблять пошук практичним.
Практична вправа далі пов’язує посилення безпеки ноди з поведінкою на рівні Пода через небезпечний Под та посилений Под. Вона не стверджує, що безпечний Под виправляє слабкий хост, але вона показує, як ті самі ідеї з’являються на різних шарах: ідентичність, записи у файлову систему, можливості, seccomp та підвищення привілеїв — усе це впливає на те, що скомпрометований процес може попросити в спільного ядра. Ноді все одно потрібне посилення безпеки хосту під обома Подами.
Привілейовані DaemonSet’и — це виняток, що підтверджує правило. Агенти мережі, сховища, логування та безпеки часто потребують просторів імен хосту, доступу до пристроїв чи підвищених можливостей, а це означає, що вони можуть стати потужними цілями після компрометації. Посильте їх, мінімізуючи вміст їхніх образів, прив’язуючи їхні привілеї до точних потреб, використовуючи виділені простори імен та сервісні акаунти й плануючи їх лише там, де цього вимагає роль ноди.
Альтернативні середовища виконання можуть змінити компроміс спільного використання ядра, але вони привносять власну ціну. Пісочничні (sandboxed) середовища виконання чи легкі підходи на основі віртуальних машин можуть надати міцнішу межу для ризикованих робочих навантажень, тоді як звичайний runc зберігає продуктивність та операційну простоту. Рішення має бути специфічним для робочого навантаження: використовуйте важчу ізоляцію там, де ризик орендаря чи недовірений код це виправдовують, і зберігайте стандартне середовище виконання для навантажень, які вже вписуються в посилений базовий профіль.
Журнали аудиту Kubernetes та журнали Linux auditd відповідають на різні питання. Аудит Kubernetes записує рішення API, як-от створення привілейованого Пода чи зміну DaemonSet, тоді як auditd може записувати зміни хостових бінарних файлів, файлів конфігурації та шляхів сертифікатів після того, як процес досягає ноди. Зрілі розслідування корелюють обидва потоки, а не очікують, що один шар пояснить активність, яка сталася в іншому.
Зберігання доказів потребує власника ще до інциденту. Якщо журнали аудиту живуть лише на ноді, зловмисник із доступом до хосту може видалити чи змінити найкорисніші записи. Пересилання подій аудиту до централізованої системи, захист часових позначок надійною синхронізацією часу та збереження достатнього часу зберігання для відкладеного виявлення перетворюють auditd із локального інструмента усунення проблем на засіб контролю безпеки.
Патерни та антипатерни
Розділ «Патерни та антипатерни»Патерни та антипатерни корисні лише тоді, коли вони змінюють рішення, яке ви ухвалили б під тиском. Для посилення безпеки ядра поширений поділ — між засобами контролю, які роблять ноду простішою, засобами контролю, які роблять експлуатацію менш інформативною, та засобами контролю, які роблять дрейф видимим. Наведена нижче таблиця тримає ці категорії окремо, щоб ви могли захистити зміну, не стверджуючи, що одне налаштування вирішує кожен ризик хосту.
| Патерн | Коли його застосовувати | Чому він працює | Міркування щодо масштабування |
|---|---|---|---|
| Незмінні чи строго перезібрані образи робочих нод | Пули нод, керовані автомасштабуванням, керованим Kubernetes чи конвеєрами образів | Замінює ручний дрейф повторюваними вхідними даними збірки й робить розгортання оновлень придатним для аудиту | Вимагає надійної автоматизації drain, заміни та відкату |
| Усвідомлений щодо Kubernetes базовий профіль sysctl | Будь-який робочий вузол, що має виконувати мережу Подів, водночас зменшуючи мережеві зловживання | Зберігає потрібне пересилання, водночас вимикаючи перенаправлення, маршрутизацію від джерела та витоки інформації ядра | Потребує специфічної для CNI валідації та задокументованого винятку для пересилання |
| Типовий seccomp середовища виконання плюс явні контексти безпеки Пода | Простори імен застосунків, де навантаження можуть працювати зі зменшеними привілеями | Звужує доступ до системних викликів, можливостей, ідентичності та файлової системи ще до перевірки хостових засобів контролю | Вимагає від власників навантажень обробки придатних для запису шляхів та сумісності непривілейованих образів |
| Цілеспрямовані правила аудиту для критичних для ноди файлів | Регульовані чи чутливі до інцидентів кластери, де докази мають значення | Записує зміни шляхів середовища виконання, kubelet, сертифікатів та сховища контейнерів, які мають бути рідкісними | Потребує зберігання журналів, маршрутизації сповіщень та контролю шуму, щоб залишатися корисним |
Найсильніший антипатерн — загальне посилення без знання платформи. Вимкнення пересилання IP, видалення залежності від CNI чи застосування noexec до шляху середовища виконання може задовольнити рядок чек-листа, водночас ламаючи кластер. Кращий підхід — задокументувати, чому Kubernetes потребує налаштування, а потім застосувати суміжні засоби контролю, що зменшують реальний ризик, не вимикаючи поведінку платформи.
| Антипатерн | Що йде не так | Чому команди в це потрапляють | Краща альтернатива |
|---|---|---|---|
| Сприйняття посилення безпеки ноди лише як політики допуску Подів | Хостові пакети, служби, файли та налаштування ядра дрейфують поза полем зору API-сервера | Нативні для Kubernetes засоби контролю легше перевіряти, ніж стан операційної системи | Поєднуйте перегляд безпеки Подів із перевірками образу ноди, sysctl, служб та середовища виконання |
| Залишення інструментів налагодження встановленими назавжди | Контейнери, що вирвалися, успадковують компілятори, оболонки, сканери та мережеві утиліти на хості | Оператори хочуть швидкого реагування на інциденти й бояться втратити аварійний доступ | Використовуйте ефемерні контейнери налагодження, доступ «розбий скло» та тимчасові робочі процеси з інструментами |
| Сліпе застосування загальних базових профілів Linux | Потрібна мережа Kubernetes чи шляхи середовища виконання перестають працювати | Шаблони відповідності часто націлені на звичайні сервери, а не на робочі вузли | Перекладайте кожен засіб контролю в терміни Kubernetes і записуйте обґрунтовані винятки |
| Аудит усього замість важливих змін | Журнали стають галасливими, дорогими та ігнорованими під час інцидентів | Більше правил аудиту здається безпечнішим, ніж вибір невеликого набору сигналів | Моніторте спершу цінні бінарні файли, конфігурації, облікові дані та шляхи сховища |
Таблиця патернів також має робити компроміси видимими. Незмінні ноди зменшують дрейф, але вимагають кращої автоматизації, суворі налаштування середовища виконання зменшують поверхню атаки, але можуть вимагати виправлень застосунків, а правила аудиту покращують докази, але споживають сховище та увагу. Тому посилена нода — це інженерна операційна модель, а не просто вставлений файл sysctl.
Рамка для ухвалення рішень
Розділ «Рамка для ухвалення рішень»Використовуйте цю рамку, коли вам потрібно вирішити, чи належить зміна посилення безпеки хосту до образу робочого вузла Kubernetes, конфігурації середовища виконання, маніфесту Пода чи операційної процедури. Перше питання — чи змінює засіб контролю потрібну поведінку платформи. Якщо так, протестуйте його в пулі нод, що відповідає стеку CNI, сховища та середовища виконання, перш ніж називати його базовим профілем.
| Точка рішення | Обирайте це, коли | Уникайте цього, коли | Сигнал перевірки |
|---|---|---|---|
| Видалення пакета з образу ноди | Програмне забезпечення не потрібне для kubelet, середовища виконання, CNI, сховища, моніторингу чи схваленого доступу | Пакет належить керованому агенту чи залежності початкового завантаження ноди | Нова нода приєднується, планує Поди, а кількість пакетів залишається стабільною між перезбірками |
| Вимкнення служби | Служба не має ролі в Kubernetes чи управлінні й слухає локально або в мережі | Власник неясний або залежності вказують на середовище виконання, мережу, сховище чи моніторинг | systemctl показує службу вимкненою, а димові тести робочих навантажень усе ще проходять |
| Посилення sysctl | Значення блокує витоки інформації чи небезпечну мережеву поведінку, не ламаючи потрібне пересилання | Загальний базовий профіль конфліктує з поведінкою CNI чи kube-proxy | Значення sysctl відповідають файлу, а трафік Под-до-Пода плюс Сервіс працює |
| Виправлення прав доступу до файлів | Конфігурація kubelet, kubeconfig, приватні ключі чи конфігурація середовища виконання доступні для читання поза їхнім власником | Керований вендором агент перезаписує файл і потребує задокументованої моделі прав | ls -la показує очікуваного власника та режим після перезавантаження чи заміни ноди |
| Ізоляція середовища виконання | Навантаження можуть працювати з меншими можливостями, непривілейованою ідентичністю, seccomp та кореневими ФС лише для читання | Застарілі образи вимагають записів від root і їх не можна швидко змінити | Под успішно запускається, а заборонені операції зазнають невдачі, як очікувалося |
| Розгортання правила аудиту | Шлях цінний і має змінюватися рідко | Правило логує високооб’ємну звичайну активність середовища виконання | Події аудиту можна шукати за ключем, а обсяг сповіщень залишається керованим |
Для швидкості на іспиті стисніть рамку до трьох питань. Чи потрібна Kubernetes ця поведінка, щоб маршрутизувати, планувати чи запускати контейнери? Якщо ні, чи можете ви видалити або обмежити її на шарі образу ноди чи середовища виконання? Якщо так, який компенсаційний засіб контролю доводить, що потрібна поведінка обмежена, а не забута?
У продакшні додайте ще одне питання: де живе зміна, щоб вона пережила заміну? Введений в оболонку ноди sysctl — це тимчасовий експеримент, тоді як конфігурація машини, збірка образу чи задокументований скрипт початкового завантаження — це базовий профіль. Та сама різниця стосується стану служб, видалення пакетів, прав доступу до файлів, правил аудиту та налаштувань середовища виконання.
Рамка також допомагає розв’язувати розбіжності з командами відповідності. Ви можете показати, що вимкнення пересилання недоречне для робочого вузла, але прийняття перенаправлень та маршрутизації від джерела зайве. Це створює точний виняток, а не розпливчасте прохання знехтувати посиленням Linux, і дає аудиторам конкретні значення для перевірки.
Остаточне правило рішення — тестувати з обох боків межі. З боку хосту перевіряйте пакети, служби, sysctl, файли, конфігурацію середовища виконання та правила аудиту. З боку Kubernetes створіть навантаження, яке доводить, що налаштування середовища виконання поводяться, як очікувалося, а потім переконайтеся, що звичайний трафік застосунків усе ще працює. Засіб контролю, який неможливо спостерігати, важко захистити під час інциденту чи іспиту.
Розставляйте пріоритети змін за радіусом ураження та оборотністю. Виправлення критичної вади ядра чи видалення відкритої зайвої служби може переважати косметичну знахідку бенчмарку, тоді як зміна мережевого sysctl на кожному пулі нод заслуговує на поетапне тестування, бо вартість відкату вища. Хороший план посилення називає, який засіб контролю відмовляє закрито, який відмовляє відкрито, і який режим відмови платформа може витримати під час розгортання.
Використовуйте пули нод як одиницю зміни. Застосування налаштування до однієї відредагованої вручну ноди мало чого вас навчить про поведінку автомасштабування, поведінку заміни чи потреби гетерогенних навантажень. Застосування його до невеликого канаркового (canary) пулу з репрезентативними агентами CNI, сховища, середовища виконання та моніторингу дає вам реальні докази, перш ніж той самий базовий профіль досягне кожного робочого вузла.
Нарешті, записуйте причину кожного винятку поруч із засобом контролю. «Пересилання IP увімкнено, бо мережа Kubernetes вимагає його на цьому CNI, з вимкненими перенаправленнями та маршрутизацією від джерела» — корисно; «виняток сканера схвалено» — ні. Майбутнім ревізорам потрібно достатньо контексту, щоб відрізнити свідому вимогу платформи від забутої прогалини в безпеці.
Чи знали ви?
Розділ «Чи знали ви?»-
Оптимізовані для контейнерів ОС, як-от Flatcar, Talos та Bottlerocket, спеціально створені для запуску контейнерів із мінімальною поверхнею атаки, і вони зазвичай підштовхують команди до заміни образу замість ручного ремонту хосту.
-
ASLR (рандомізація розташування адресного простору) робить багато атак на пошкодження пам’яті менш надійними, бо локації пам’яті процесу змінюються замість того, щоб залишатися фіксованими — саме тому
kernel.randomize_va_space = 2є поширеною базовою перевіркою. -
Простори імен користувачів можуть забезпечити додаткову ізоляцію, відображаючи root контейнера на непривілейованого користувача хосту, але підтримка та операційні типові значення різняться залежно від середовища виконання, дистрибутива та зрілості функції Kubernetes.
-
Системи живого виправлення ядра (kernel live patching), як-от Ubuntu Livepatch та RHEL kpatch, можуть зменшити потребу в перезавантаженні для деяких виправлень безпеки, але вони не усувають потребу в плановій заміні ноди та повному керуванні життєвим циклом ядра.
Типові помилки
Розділ «Типові помилки»Більшість помилок у посиленні безпеки ядра спричинені не незнанням команди; вони спричинені застосуванням команди на хибному шарі чи без шляху відкату. Використовуйте цю таблицю як діагностичний чек-лист, коли сканер, іспитове питання чи продакшн-огляд повідомляє про слабку позицію ноди.
| Помилка | Чому вона стається | Як її виправити |
|---|---|---|
| Нерегулярне встановлення оновлень | Відомі CVE залишаються придатними для експлуатації, бо образи нод чи живі ноди вважаються стабільними назавжди | Автоматизуйте перезбірки образів чи схвалені оновлення безпеки, потім виконуйте drain та заміну нод за перевіреним розкладом |
| Типова конфігурація SSH | Вхід root чи автентифікація за паролем виживають, бо SSH вважається питанням операцій, а не межею безпеки ноди | Вимкніть SSH для root, вимкніть паролі, обмежте дозволених користувачів і надавайте перевагу контрольованим робочим процесам «розбий скло» |
| Забагато служб | Базові образи успадковують демони друку, виявлення, бездротового зв’язку чи RPC, які не обслуговують навантаження Kubernetes | Проінвентаризуйте запущені служби, визначте власника, вимкніть зайві юніти в образі й повторно протестуйте планування |
| Хибні права доступу до файлів | Конфігурації kubelet, kubeconfig чи приватні ключі створюються скриптами початкового завантаження з широким доступом на читання | Установіть володіння root, обмежте приватні файли режимом 600 і перевірте права після заміни ноди |
| Відсутність логування аудиту | Ті, хто реагує на інциденти, не можуть довести, чи змінилися бінарні файли середовища виконання, файли kubelet чи шляхи сертифікатів | Розгорніть цілеспрямовані правила auditd для цінних шляхів і маршрутизуйте події з ключами до збережених журналів |
| Сліпе вимкнення пересилання IP | Загальний базовий профіль Linux копіюється на робочі вузли без розуміння мережі Подів | Залиште потрібне пересилання ввімкненим, задокументуйте виняток Kubernetes і натомість вимкніть перенаправлення та маршрутизацію від джерела |
| Залишення інструментів налагодження на нодах | Зручність усунення проблем поступово перетворюється на постійний інструментарій зловмисника після втечі з контейнера | Перенесіть рутинне налагодження на kubectl debug, ефемерні контейнери та тимчасові схвалені шляхи доступу |
Тест
Розділ «Тест»Кожне питання описує рішення щодо посилення безпеки ноди, а не просить запам’ятану команду. Прочитайте сценарій, оберіть перше, що ви б перевірили, а потім порівняйте своє міркування з відповіддю, перш ніж рухатися далі.
Ваша команда встановлює `net.ipv4.ip_forward = 0` на кожному робочому вузлі, бо загальний бенчмарк Linux рекомендує вимикати пересилання. Трафік Под-до-Пода між нодами одразу ламається, але команда безпеки все одно хоче доказів, що виняток обґрунтований. Що ви перевіряєте і як пояснюєте безпечніший шлях посилення?
Перевірте поточне значення пересилання, з’ясуйте шлях трафіку CNI чи kube-proxy, що вимагає пересилання, і зберіть простий збій Под-до-Пода чи Под-до-Сервісу, який відновлюється, коли пересилання повернуто. Робочі вузли Kubernetes часто потребують пересилання, бо пакети рухаються між інтерфейсами Подів, оверлейними чи мостовими пристроями та інтерфейсом ноди. Безпечніший шлях — не приймати кожну мережеву функцію; залиште пересилання як задокументовану вимогу Kubernetes, водночас вимикаючи перенаправлення, маршрутизацію від джерела та інші види поведінки, що дозволяють недовіреним вузлам впливати на маршрутизацію. Ця відповідь узгоджує діагностику sysctl із моделлю мережі спільного ядра.
Зловмисник вирвався з контейнера як непривілейований користувач хосту й намагається прочитати `dmesg` плюс інформацію про вказівники ядра, щоб обрати експлойт підвищення привілеїв. Які значення `sysctl` зменшують цю розвідку й чому вони корисні, навіть якщо не виправляють саму вразливість?
Установіть kernel.dmesg_restrict = 1, щоб непривілейовані користувачі не могли читати повідомлення кільцевого буфера ядра, та встановіть kernel.kptr_restrict = 1 чи 2, щоб зменшити розкриття адрес вказівників ядра. Ці налаштування не усувають ваду ядра, але вони усувають інформацію, яка може зробити експлуатацію надійнішою. Це засоби контролю глибокого захисту для фази після того, як зловмисник отримав певне локальне виконання, але до того, як він має надійний експлойт хосту. Поєднуйте їх зі своєчасним встановленням оновлень ядра, бо засоби контролю секретності не є замінниками усунення вразливостей.
Образ робочого вузла містить настільні утиліти, інструменти збірки, бінарні файли усунення мережевих проблем та кілька служб, якими ніхто не володіє. Команда операцій каже, що інструменти полегшують налагодження збоїв. Як спроєктувати мінімальний базовий профіль хостової ОС, не залишаючи тих, хто реагує, сліпими?
Почніть із визначення потрібних функцій ноди: середовище виконання контейнерів, kubelet, підтримка CNI, синхронізація часу, схвалений моніторинг та контрольований доступ управління. Видаліть непов’язані пакети та служби в конвеєрі образів, а не разовим очищенням оболонки, потім переконайтеся, що свіжа нода може приєднатися, планувати Поди та повідомляти про справність. Для потреб реагування використовуйте ефемерні контейнери налагодження, схвалений доступ «розбий скло» та тимчасові робочі процеси з інструментами замість постійних інструментів на кожному робочому вузлі. Це зберігає операційну видимість, водночас зменшуючи те, що контейнер, який вирвався, може повторно використати на хості.
Під час аудиту хосту `/var/lib/kubelet/config.yaml` доступний для читання всім, а приватний ключ під `/etc/kubernetes/pki` має широкі права доступу. Який ризик це створює і які докази має залишити ваше виправлення?
Ризик — розкриття конфігурації kubelet, kubeconfig, сертифікатів чи приватних ключів, що можуть допомогти зловмиснику автентифікуватися на API-сервері чи видавати себе за компоненти ноди. Виправте володіння та права так, щоб чутливі файли kubelet та приватні ключі належали root з обмежувальними режимами на кшталт 600, тоді як публічні сертифікати залишаються лише для читання. Докази мають містити вивід ls -la після зміни і, в ідеалі, конфігурацію образу чи початкового завантаження, що відтворить ті самі права на нодах-замінах. Без збереження виправлення може зникнути під час наступної перезбірки.
Сканер позначає відсутність `hidepid=2` на `/proc`, але агент моніторингу покладається на видимість процесів. Як ви вирішуєте, чи застосовувати налаштування, і з якою концепцією Kubernetes його не можна плутати?
Спершу з’ясуйте, чи агент моніторингу справді потребує видимості процесів на рівні всього хосту й чи може він працювати з виділеною групою чи альтернативним методом збору. hidepid=2 — це поведінка монтування хосту для локальної видимості процесів, тоді як налаштування простору імен процесів Пода в Kubernetes контролюють те, що бачать контейнери всередині власних просторів імен. Не стверджуйте, що контекст безпеки Пода автоматично виправляє розкриття /proc хосту. Якщо ви зберігаєте ширшу видимість для агента, задокументуйте цей виняток і обмежте ідентичність та шлях доступу агента.
Безпечний маніфест Пода встановлює `runAsNonRoot`, скидає всі можливості, використовує seccomp `RuntimeDefault`, вимикає підвищення привілеїв і встановлює кореневу файлову систему лише для читання. Нода все одно запускає старі служби й має слабкі `sysctl` ядра. Чи розв'язала команда посилення безпеки ядра?
Ні. Маніфест Пода зменшує те, що це навантаження може робити, перш ніж досягне межі ядра, що цінно, але він не виправляє хост, не видаляє зайвих демонів, не захищає файли kubelet і не обмежує витоки інформації ядра для інших локальних користувачів. Посилення безпеки ядра та ОС має відбуватися також на шарах образу ноди, конфігурації середовища виконання, sysctl, файлової системи та аудиту. Правильна оцінка багатошарова: Под краще ізольований, але нода все одно має прогалини на рівні хосту, що можуть вплинути на кожне навантаження, заплановане там.
Ви вмикаєте auditd і створюєте широкі правила, що логують величезний обсяг активності середовища виконання контейнерів. Через тиждень команда безпеки ігнорує сповіщення, бо майже все виглядає галасливим. Як би ви переспроєктували правила аудиту для посилення безпеки ядра та ноди?
Зосередьте правила аудиту на цінних шляхах, де зміни мають бути рідкісними: бінарні файли середовища виконання, каталоги конфігурації середовища виконання, конфігурація Kubernetes, стан kubelet, сертифікати та метадані сховища контейнерів. Використовуйте змістовні ключі, щоб ті, хто реагує, могли швидко шукати події containerd, kubelet чи kubernetes. Уникайте логування звичайної високооб’ємної активності контейнерів, якщо немає конкретної потреби в розслідуванні, бо надмірний обсяг приховує важливі зміни й може вичерпати сховище. Хороший дизайн аудиту доводить дрейф та підробку, не перетворюючи кожне звичайне навантаження на шум сповіщень.
Перевірка засвоєння
Розділ «Перевірка засвоєння»Лабораторна робота з посилення безпеки корисна лише тоді, коли ви можете назвати точну межу ядра, яку вона довела, і межу, яку вона лише оглянула.
Перш ніж довіритися команді як доказу, запитайте, чи перевіряє вона засіб контролю, названий в уроці. Невдале читання /etc/shadow з непривілейованого контейнера доводить звичайні права доступу до файлів та ідентичність користувача, а не allowPrivilegeEscalation: false. Для цього засобу контролю перевірте прапор Linux NoNewPrivs або виконайте навмисно обмежену демонстрацію setuid у одноразовій лабораторії.
Практична вправа
Розділ «Практична вправа»Ця вправа використовує контексти безпеки Kubernetes, щоб безпечно продемонструвати концепції посилення безпеки хосту. Ви порівняєте небезпечний Под із посиленим Подом, а потім зіставите кожну спостережену відмінність із засобом контролю ядра чи ОС, на який вона схожа. Якщо ви працюєте на реальному кластері, використовуйте одноразовий простір імен і уникайте запуску привілейованих експериментів на продакшн-нодах.
Підготовка
Розділ «Підготовка»Запустіть наведений нижче збережений лабораторний скрипт у тестовому кластері, де ви можете створити та видалити простір імен. Скрипт розгортає два Поди BusyBox, порівнює ідентичність, файлову систему, типовий простір імен PID Пода, /proc, NoNewPrivs та поведінку контексту безпеки, а потім друкує хостові перевірки sysctl, які ви б виконали на самій ноді. Він навмисно використовує повні команди kubectl, щоб блок працював у неінтерактивних оболонках.
Завдання
Розділ «Завдання»- Продіагностуйте поточну різницю в безпеці між небезпечним Подом та безпечним Подом, порівнявши ідентичність користувача, вивід контексту безпеки та поведінку запису.
- Спроєктуйте мінімальний базовий профіль хостової ОС для того самого пулу нод, перелічивши, які пакети, служби, налаштування SSH та робочий процес оновлень ви б вимагали перед продакшном.
- Проведіть аудит конфігурації kubelet, прав доступу до сертифікатів, видимості
/proc, відкритості/sysта покриття auditd на реальному чи симульованому робочому вузлі. - Оцініть ізоляцію середовища виконання контейнерів, пояснивши, як seccomp, скинуті можливості, кореневі файлові системи лише для читання та засоби контролю підвищення привілеїв зменшують ризик, спрямований на ядро.
- Перевірте потрібний Kubernetes виняток
sysctlдля пересилання IP, водночас підтвердивши, що перенаправлення, маршрутизація від джерела, доступ до dmesg та розкриття вказівників ядра обмежені.
Посібник з розв'язання для завдання 1
Небезпечний Под має працювати з типовою ідентичністю та придатною для запису файловою системою, тоді як безпечний Под має працювати як UID 1000, показувати контекст безпеки на рівні Пода й зазнавати невдачі під час записів, спрямованих на кореневу файлову систему лише для читання. Сприймайте кожну відмінність як обмеження, спрямоване на ядро: ідентичність зменшує припущення про root, коренева ФС лише для читання зменшує цілі для запису, скинуті можливості усувають привілейовані операції, а seccomp звужує доступ до системних викликів. Якщо одна з цих перевірок поводиться інакше у вашому кластері, перевірте політики допуску та типові значення середовища виконання, перш ніж припускати, що маніфест проігноровано.
Посібник з розв'язання для завдання 2
Мінімальний базовий профіль містить середовище виконання контейнерів, kubelet, залежності CNI, синхронізацію часу, схвалений моніторинг та контрольований шлях управління. Видаліть непов’язані пакети та служби з образу ноди, вимкніть SSH для root та автентифікацію за паролем, якщо SSH існує, і оберіть робочий процес оновлень на кшталт заміни образу чи схвалених автоматичних оновлень безпеки. Умова успіху — не ідеальна кількість пакетів; це те, що свіжа нода може приєднатися до кластера, запускати навантаження й відтворити той самий посилений стан.
Посібник з розв'язання для завдання 3
Перевірте, що конфігурація kubelet та kubeconfig належать root і є обмежувальними, приватні ключі під шляхами сертифікатів Kubernetes не доступні для широкого читання, а видимість /proc хосту навмисно налаштована. Перегляньте, чи отримують контейнери чи агенти широкі монтування /sys, потім переконайтеся, що auditd стежить за бінарними файлами середовища виконання, конфігурацією середовища виконання, шляхами kubelet та каталогами сертифікатів Kubernetes. Докази мають пережити заміну ноди, тож надавайте перевагу конфігурації образу чи початкового завантаження над ручним ремонтом.
Посібник з розв'язання для завдання 4
Оцініть ізоляцію середовища виконання, запитуючи, що навантаження може попросити в ядра після компрометації. Seccomp RuntimeDefault усуває багато непотрібних шляхів системних викликів, скидання можливостей зменшує привілейовані операції ядра, allowPrivilegeEscalation: false відображається на прапор Linux NoNewPrivs, а коренева файлова система лише для читання усуває легкі локації для закріплення. Ці засоби контролю найсильніші, коли їх поєднано зі встановленням оновлень хосту, обмеженнями sysctl, мінімальними пакетами та цілеспрямованими доказами аудиту.
Посібник з розв'язання для завдання 5
Перевірте net.ipv4.ip_forward, net.bridge.bridge-nf-call-iptables та документацію CNI для вашого кластера, перш ніж змінювати поведінку пересилання. Залишайте пересилання ввімкненим, коли цього вимагає площина даних, потім переконайтеся, що accept_redirects, send_redirects та accept_source_route вимкнені й що kernel.dmesg_restrict плюс kernel.kptr_restrict встановлені. Хороша відповідь відрізняє потрібне Kubernetes пересилання від зайвих функцій мережевої довіри.
Лабораторний скрипт
Розділ «Лабораторний скрипт»# Since we can't modify the host kernel from Kubernetes, we'll demonstrate# how kernel hardening concepts translate to container security.
# Step 1: Create namespace for testingkubectl create namespace kernel-test
# Step 2: Deploy pod WITHOUT security hardening (insecure baseline)cat <<EOF | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: insecure-pod namespace: kernel-testspec: containers: - name: app image: busybox command: ["sleep", "3600"] # No security context = dangerous!EOF
# Step 3: Deploy pod WITH security hardening (secure)cat <<EOF | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: secure-pod namespace: kernel-testspec: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 seccompProfile: type: RuntimeDefault containers: - name: app image: busybox command: ["sleep", "3600"] securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALLEOF
# Wait for pods to be readykubectl wait --for=condition=Ready pod/insecure-pod -n kernel-test --timeout=60skubectl wait --for=condition=Ready pod/secure-pod -n kernel-test --timeout=60s
# Step 4: Compare what each pod can doecho "=== Insecure Pod: Who am I? ==="kubectl exec -n kernel-test insecure-pod -- id
echo "=== Secure Pod: Who am I? ==="kubectl exec -n kernel-test secure-pod -- id
# Step 5: Test filesystem accessecho "=== Insecure Pod: Can write to /tmp? ==="kubectl exec -n kernel-test insecure-pod -- sh -c "echo 'test' > /tmp/test.txt && echo 'Write succeeded' || echo 'Write failed'"
echo "=== Secure Pod: Can write to /tmp? (should fail - readOnlyRootFilesystem) ==="kubectl exec -n kernel-test secure-pod -- sh -c "echo 'test' > /tmp/test.txt && echo 'Write succeeded' || echo 'Write blocked!'"
# Step 6: Observe default Pod PID namespace visibilityecho "=== Insecure Pod: Process list inside its Pod PID namespace ==="kubectl exec -n kernel-test insecure-pod -- ps aux | head -5
echo "=== Secure Pod: Process list inside its Pod PID namespace ==="kubectl exec -n kernel-test secure-pod -- ps aux | head -5echo "Both Pods use normal isolated Pod PID namespaces; host hidepid must be checked on the node."
# Step 7: Check proc accessecho "=== Checking /proc access in secure pod ==="kubectl exec -n kernel-test secure-pod -- cat /proc/1/cmdline 2>&1 | tr '\0' ' ' && echo ""
# Step 8: Check security context appliedecho "=== Security Context Comparison ==="echo "Insecure pod security context:"kubectl get pod insecure-pod -n kernel-test -o jsonpath='{.spec.securityContext}' && echo ""echo "Secure pod security context:"kubectl get pod secure-pod -n kernel-test -o jsonpath='{.spec.securityContext}' && echo ""
# Step 9: Verify allowPrivilegeEscalation through no_new_privsecho "=== no_new_privs flag (allowPrivilegeEscalation=false) ==="echo "Insecure pod:"kubectl exec -n kernel-test insecure-pod -- sh -c "grep NoNewPrivs /proc/self/status"echo "Secure pod:"kubectl exec -n kernel-test secure-pod -- sh -c "grep NoNewPrivs /proc/self/status"
# Step 10: Check non-root permissions without confusing them for no_new_privsecho "=== Non-root file permission check ==="kubectl exec -n kernel-test secure-pod -- sh -c "cat /etc/shadow 2>&1" || echo "Root-only file blocked for non-root user (expected)"
# Step 11: Check host sysctl (if running on actual node)echo ""echo "=== Host Kernel Checks (run on actual node) ==="echo "To check on your actual cluster nodes:"echo " sysctl kernel.randomize_va_space # Should be 2"echo " sysctl kernel.dmesg_restrict # Should be 1"echo " sysctl kernel.kptr_restrict # Should be 1 or 2"echo " sysctl net.ipv4.conf.all.accept_redirects # Should be 0"echo " findmnt -no OPTIONS /proc # Check host hidepid options on the node"
# Cleanupecho ""echo "=== Cleanup ==="kubectl delete namespace kernel-test
echo ""echo "=== Exercise Complete ==="echo "Key learnings demonstrated:"echo "1. ✓ runAsNonRoot prevents root execution"echo "2. ✓ readOnlyRootFilesystem blocks writes"echo "3. ✓ Dropping capabilities limits syscalls"echo "4. ✓ allowPrivilegeEscalation=false maps to NoNewPrivs"echo "5. ✓ seccompProfile applies syscall filtering"echo "6. ✓ default Pod PID namespaces are not the same as host hidepid"Критерії успіху
Розділ «Критерії успіху»- Ви можете пояснити, чому контейнери ділять ядро хосту і чому це робить посилення безпеки ноди відмінним від посилення безпеки віртуальної машини.
- Ви можете показати щонайменше три хостові перевірки для пакетів, служб, SSH,
sysctl, файлів kubelet чи правил аудиту. - Ви можете визначити налаштування мережі Kubernetes, які мають залишатися ввімкненими, та небезпечні види мережевої поведінки, що мають залишатися вимкненими.
- Ви можете пов’язати кожне налаштування безпечного Пода в лабораторії зі зменшенням ризику, спрямованого на ядро.
- Ви можете описати, де має жити кожна зміна посилення, щоб вона пережила перезавантаження, автомасштабування та заміну ноди.
Джерела
Розділ «Джерела»- Документація Kubernetes: обмеження безпеки ядра Linux для Подів та контейнерів
- Документація Kubernetes: Pod Security Standards
- Документація Kubernetes: налаштування контексту безпеки для Пода чи контейнера
- Документація Kubernetes: обмеження системних викликів контейнера за допомогою seccomp
- Документація Kubernetes: налагодження запущених Подів
- Документація Kubernetes: налагодження нод Kubernetes за допомогою crictl
- Документація ядра Linux: параметри ядра sysctl
- Документація ядра Linux: налаштування IP sysctl
- Домашня сторінка проєкту ядра
- Документація containerd: конфігурація
- Специфікація середовища виконання Open Container Initiative: конфігурація Linux
- Документація Docker: безпека Docker Engine
- Настанови з посилення безпеки Kubernetes від CISA та NSA
Наступний модуль
Розділ «Наступний модуль»Модуль 3.4: Мережева безпека — посилення безпеки мережі на рівні хосту.