Hartowanie jadra Linux w 2026: sysctl, Seccomp, Landlock i KSPP w praktyce

Praktyczny przewodnik po hartowaniu jadra Linux w 2026 roku. Od parametrow sysctl i opcji KSPP, przez Seccomp-BPF i Landlock LSM, po audyt z kernel-hardening-checker i automatyzacje Ansible.

Wprowadzenie — dlaczego hartowanie jadra ma znaczenie w 2026 roku

Jadro systemu Linux to fundament wspolczesnej infrastruktury IT — od serwerow chmurowych i kontenerow, przez urzadzenia IoT, az po systemy wbudowane w infrastrukturze krytycznej. Jako warstwa posredniczaca miedzy sprzetem a przestrzenia uzytkownika, jadro posiada najwyzsze uprawnienia w systemie i kontroluje kazdy aspekt jego dzialania. Kompromitacja jadra oznacza pelna kontrole nad maszyna. Bez wyjatkow.

Skala zagrozen w 2026 roku jest, szczerze mowiac, bezprecedensowa. W 2025 roku zarejestrowano ponad 5530 podatnosci CVE dotyczacych jadra Linuksa — to srednio 8-9 nowych CVE dziennie. Zeby lepiej to zobrazowac: tylko w pierwszych 16 dniach 2025 roku opublikowano 134 nowe CVE jadra, przekraczajac calkowita liczbe z lat 2020 i 2021. Czesciowo wynika to z faktu, ze zespol jadra Linux stal sie w 2024 roku organem CVE Numbering Authority (CNA), co dramatycznie przyspieszilo tempo ujawniania podatnosci.

Ale liczby to jedno. Jeszcze bardziej niepokojace sa realne konsekwencje tych podatnosci.

Grupy ransomware takie jak Qilin i RansomHub aktywnie wykorzystuja exploity jadra w swoich kampaniach. Qilin w 2025 roku zaatakowal ponad 700 organizacji w 62 krajach, a na poczatku 2026 roku dalej przyspieszal — publikujac 55 ofiar tylko w pierwszych tygodniach nowego roku. Co ciekawe, ta grupa pioniersko wykorzystywala enkryptory linuksowe nawet na hostach Windows, poprzez instalacje WSL na skompromitowanych systemach i uruchamianie binarek ELF wewnatrz tego srodowiska. Pomyslowe, prawda?

W tym kontekscie hartowanie jadra (kernel hardening) nie jest juz opcjonalnym zadaniem dla entuzjastow bezpieczenstwa — to krytyczny wymog operacyjny dla kazdej organizacji korzystajacej z Linuksa. Ten przewodnik przeprowadzi Cie przez kompleksowy proces zabezpieczania jadra — od parametrow sysctl, przez opcje kompilacji, az po zaawansowane mechanizmy sandboxingu jak Seccomp i Landlock.

Powierzchnia ataku jadra Linux — co czyni jadro podatnym

Zanim zabierzemy sie za hartowanie, warto zrozumiec, z czym wlasciwie mamy do czynienia. Jadro Linux to ogromna baza kodu — ponad 30 milionow linii — z wieloma podsystemami, z ktorych kazdy moze zawierac podatnosci.

Wywolania systemowe (syscalls)

Interfejs wywolan systemowych to glowna brama komunikacji miedzy przestrzenia uzytkownika a jadrem. Linux udostepnia ponad 300 syscalli, z ktorych kazdy stanowi potencjalny wektor ataku. Atakujacy moga wykorzystywac bledy w implementacji konkretnych syscalli do eskalacji uprawnien lub ucieczki z sandboxa. Wlasnie dlatego mechanizmy takie jak Seccomp — o ktorych powiemy wiecej dalej — sa tak istotne.

Sterowniki urzadzen

Sterowniki stanowia znaczna czesc kodu jadra i, niestety, czesto sa pisane przez zewnetrznych deweloperow z roznym poziomem doswiadczenia w bezpiecznym programowaniu. Dzialaja z pelnym dostepem do pamieci jadra, wiec blad w sterowniku moze prowadzic do pelnej kompromitacji systemu. W 2026 roku szczegolna uwage nalezy zwrocic na sterowniki podsystemu SCSI — podatnosc CVE-2026-23110 ujawnila warunek wyscigu (race condition) w sterowniku SCSI, ktory mogl prowadzic do uszkodzenia pamieci jadra i potencjalnej eskalacji uprawnien.

Zarzadzanie pamiecia

Bledy w zarzadzaniu pamiecia jadra — use-after-free, double-free, przepelnienie bufora, wycieki informacji — to jedna z najczestszych klas podatnosci. Klasycznym (i dosc przerazajacym) przykladem jest CVE-2024-1086, podatnosc use-after-free w komponencie netfilter. Funkcja nft_verdict_init() pozwalala na ustawienie dodatnich wartosci jako bledow drop w werdyktach hookow, co prowadzilo do podwojnego zwolnienia pamieci i umozliwialo lokalna eskalacje uprawnien do poziomu root.

Ta podatnosc byla obecna w jadrze od ponad dekady (od wersji 3.15 do 6.8-rc1) i byla aktywnie wykorzystywana w kampaniach ransomware — CISA potwierdzila to oficjalnie w pazdzierniku 2025 roku. Dekada niezauwazenia — to daje do myslenia.

Podsystem sieciowy

Stos sieciowy jadra to kolejny rozlegly obszar ataku. Obejmuje implementacje protokolow TCP/IP, filtrowanie pakietow (netfilter/nftables), obsluge gniazd i wiele innych komponentow. Kazdy z nich moze zawierac bledy osiagalne zdalnie lub lokalnie.

Mechanizmy wirtualizacji i komunikacji miedzy maszynami wirtualnymi

Szczegolnie groznie wyglada podatnosc CVE-2025-21756, okreslana jako "Attack of the Vsock". Dotyczy podsystemu Virtual Socket (vsock) jadra Linux, odpowiedzialnego za komunikacje miedzy maszynami wirtualnymi a hostem. Blad w zarzadzaniu wiazaniami gniazd podczas ponownego przypisywania transportu prowadzil do nieprawidlowego zliczania referencji, co umozliwialo atakujacemu wewnatrz maszyny wirtualnej ucieczkke do hosta i uzyskanie dostepu root. W srodowiskach chmurowych z wieloma dzierzawcami — a takich jest coraz wiecej — taka podatnosc ma katastrofalne konsekwencje.

Parametry sysctl do hartowania jadra

No dobrze, przejdzmy do konkretow. Parametry sysctl to jeden z najszybszych i najlatwiejszych sposobow na poprawe bezpieczenstwa jadra. Mozna je zmieniac w czasie rzeczywistym, bez rekompilacji jadra czy restartu systemu. Ponizej znajdziesz kompleksowy zestaw zalecanych ustawien.

Ograniczenie dostepu do informacji o jadrze

Pierwszym krokiem jest ograniczenie informacji, ktore atakujacy moze pozyskac o jadrze:

  • kernel.dmesg_restrict=1 — ogranicza dostep do logow jadra (dmesg) tylko do uzytkownika root. Logi jadra czesto zawieraja adresy pamieci i inne informacje przydatne przy tworzeniu exploitow.
  • kernel.kptr_restrict=2 — ukrywa wskazniki jadra w /proc/kallsyms i innych interfejsach. Wartosc 2 ukrywa je nawet przed rootem, co utrudnia tworzenie exploitow opartych na znajomosci ukladu pamieci jadra.
  • kernel.perf_event_paranoid=3 — calkowicie blokuje dostep do podsystemu perf dla nieuprzywilejowanych uzytkownikow. Podsystem perf byl wielokrotnie wykorzystywany jako wektor ataku, wiec lepiej go po prostu odciac.

Ochrona procesow i pamieci

  • kernel.yama.ptrace_scope=2 — ogranicza uzycie ptrace() tylko do procesow z uprawnieniami CAP_SYS_PTRACE. Ptrace umozliwia debugowanie i manipulowanie innymi procesami — atakujacy moga go wykorzystac do kradzizy danych z pamieci lub wstrzykiwania kodu.
  • kernel.randomize_va_space=2 — wlacza pelna randomizacje ukladu przestrzeni adresowej (ASLR), wlaczajac randomizacje stosu, bibliotek, mmap, VDSO i sterty. ASLR znaczaco utrudnia exploitacje bledow pamieci.
  • fs.suid_dumpable=0 — zapobiega tworzeniu zrzutow pamieci (core dumps) dla programow z ustawionymi bitami SUID/SGID. Zrzuty takie moglyby zawierac poufne dane.
  • fs.protected_hardlinks=1 — zapobiega tworzeniu dowiazan twardych do plikow, ktorych uzytkownik nie jest wlascicielem. Chroni przed atakami polegajacymi na tworzeniu hardlinkow do plikow SUID.
  • fs.protected_symlinks=1 — podobna ochrona dla dowiazan symbolicznych w katalogach z ustawionym sticky bitem.

Ograniczenie BPF i JIT

  • kernel.unprivileged_bpf_disabled=1 — blokuje dostep do BPF dla nieuprzywilejowanych uzytkownikow. BPF umozliwia uruchamianie programow w jadrze, co moze byc wykorzystane do atakow takich jak heap spraying.
  • net.core.bpf_jit_harden=2 — wlacza pelne utwardzanie kompilatora JIT dla BPF. Bez utwardzania, kompilator JIT moze byc wykorzystany do generowania gadzetow ROP lub przeprowadzania atakow bocznokanalkowych.

Parametry sieciowe

Stos sieciowy jadra wymaga osobnego zestawu zabezpieczen — i szczerze mowiac, to jest obszar, ktory administratorzy najczesciej pomijaja:

  • net.ipv4.conf.all.rp_filter=1 — wlacza Reverse Path Filtering w trybie scislym. Odrzuca pakiety, ktorych adres zrodlowy nie jest osiagalny przez interfejs, na ktorym zostaly odebrane — chroni przed spoofingiem IP.
  • net.ipv4.tcp_syncookies=1 — wlacza SYN cookies jako ochrone przed atakami SYN flood.
  • net.ipv4.conf.all.accept_redirects=0 — blokuje akceptowanie przekierowan ICMP, ktore moga byc wykorzystane do manipulowania tablicami routingu.
  • net.ipv6.conf.all.accept_redirects=0 — to samo dla IPv6.
  • net.ipv4.conf.all.accept_source_route=0 — blokuje pakiety z opcja source routing, ktora pozwala nadawcy okreslic trase pakietu i moze byc wykorzystana do ominiecia firewalli.
  • net.ipv4.conf.all.log_martians=1 — wlacza logowanie pakietow z niemozliwymi adresami zrodlowymi, co pomaga w wykrywaniu prob atakow.
  • net.ipv4.icmp_echo_ignore_broadcasts=1 — ignoruje ICMP echo wysylane na adresy broadcastowe, zapobiegajac atakom typu Smurf.
  • net.ipv4.icmp_ignore_bogus_error_responses=1 — ignoruje falszywe odpowiedzi ICMP.
  • net.ipv4.conf.all.send_redirects=0 — blokuje wysylanie przekierowan ICMP. Serwery nie powinny dzialac jako routery.
  • net.ipv4.tcp_timestamps=0 — wylacza znaczniki czasowe TCP, ktore moga wyciekac informacje o czasie dzialania systemu.

Kompletny plik konfiguracyjny

Ponizej znajdziesz kompletny plik konfiguracyjny, ktory mozesz umiescic w /etc/sysctl.d/99-hardening.conf:

# /etc/sysctl.d/99-hardening.conf
# Kompleksowa konfiguracja hartowania jadra Linux 2026

# === Ograniczenie dostepu do informacji o jadrze ===
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
kernel.perf_event_paranoid = 3

# === Ochrona procesow i pamieci ===
kernel.yama.ptrace_scope = 2
kernel.randomize_va_space = 2
fs.suid_dumpable = 0
fs.protected_hardlinks = 1
fs.protected_symlinks = 1

# === Ograniczenie BPF ===
kernel.unprivileged_bpf_disabled = 1
net.core.bpf_jit_harden = 2

# === Ochrona stosu sieciowego IPv4 ===
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_timestamps = 0

# === Ochrona stosu sieciowego IPv6 ===
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0

Aby zastosowac te ustawienia, wystarczy jedno polecenie:

sudo sysctl --system

A zeby sprawdzic, czy wszystko zadzialo:

# Weryfikacja wybranego parametru
sudo sysctl kernel.dmesg_restrict

# Wyswietlenie wszystkich aktywnych parametrow
sudo sysctl -a

# Weryfikacja pelnego pliku konfiguracyjnego
sudo sysctl -p /etc/sysctl.d/99-hardening.conf

Opcje kompilacji jadra — zalecenia KSPP

Kernel Self Protection Project (KSPP) to inicjatywa majaca na celu wbudowanie mechanizmow ochronnych bezposrednio w jadro Linux. Opcje kompilacji stanowia pierwsza linie obrony, poniewaz aktywuja zabezpieczenia na poziomie kodu jadra. Wymagaja rekompilacji jadra, ale zapewniaja znacznie glebsza ochrone niz parametry sysctl.

Ochrona stosu

CONFIG_STACKPROTECTOR=y
CONFIG_STACKPROTECTOR_STRONG=y

CONFIG_STACKPROTECTOR_STRONG rozszerza ochrone stosu (stack canaries) na wieksza liczbe funkcji niz podstawowa wersja. Kompilator umieszcza losowa wartosc — tzw. canary — przed adresem powrotu na stosie. Jesli przepelnienie bufora nadpisze te wartosc, jadro wykryje to przed powrotem z funkcji i zapobiegnie wykonaniu kodu atakujacego. Proste, a skuteczne.

Utwardzanie alokatora pamieci (SLAB)

CONFIG_SLAB_FREELIST_RANDOM=y
CONFIG_SLAB_FREELIST_HARDENED=y
CONFIG_RANDOM_KMALLOC_CACHES=y

CONFIG_SLAB_FREELIST_RANDOM randomizuje kolejnosc obiektow na listach wolnych alokatora SLAB, utrudniajac atakujacemu przewidzenie ukladu pamieci. CONFIG_SLAB_FREELIST_HARDENED dodaje zabezpieczenia metadanych listy wolnych — weryfikuje integralnosc wskaznikow i utrudnia techniki exploitacji. Natomiast CONFIG_RANDOM_KMALLOC_CACHES to nowsza opcja, ktora tworzy wiele kopii cache'y kmalloc i losowo przydziela alokacje miedzy nimi, co dalej utrudnia ataki typu heap spraying.

Ochrona pamieci urzadzen

CONFIG_STRICT_DEVMEM=y
CONFIG_IO_STRICT_DEVMEM=y

Te opcje ograniczaja dostep do fizycznej pamieci przez /dev/mem. Bez nich atakujacy z dostepem do /dev/mem moglby bezposrednio czytac i zapisywac pamiec jadra — a tego zdecydowanie nie chcemy.

Lockdown LSM

CONFIG_SECURITY_LOCKDOWN_LSM=y
CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y
CONFIG_LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY=y

Lockdown LSM to modul bezpieczenstwa ograniczajacy operacje, ktore moga modyfikowac dzialajace jadro lub wyciagac z niego poufne informacje. W trybie "confidentiality" blokuje dostep do /dev/mem, /dev/kmem, niestandardowe moduly jadra, kexec, hibernacje i inne mechanizmy, ktore moglyby ujawnic lub zmodyfikowac stan jadra. Osobiscie uwazam, ze to jedna z najwazniejszych opcji kompilacji do wlaczenia na serwerach produkcyjnych.

Inicjalizacja pamieci

CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y
CONFIG_INIT_ON_FREE_DEFAULT_ON=y

Te opcje zapewniaja, ze pamiec jest zerowana zarowno przy alokacji, jak i przy zwolnieniu. Zapobiega to wyciekom informacji z poprzednio uzywanych buforow i utrudnia exploitacje bledow use-after-free, poniewaz atakujacy nie moze polegac na tym, ze zwolniona pamiec nadal zawiera przydatne dane.

Utwardzanie kopiowania danych uzytkownika

CONFIG_HARDENED_USERCOPY=y

CONFIG_HARDENED_USERCOPY dodaje sprawdzenia granic podczas kopiowania danych miedzy przestrzenia uzytkownika a jadrem. Weryfikuje, ze kopiowane dane mieszcza sie w oczekiwanych obiektach SLAB i nie przekraczaja ich granic — zapobiegajac calym klasom bledow przepelnienia bufora.

Dodatkowe zalecane opcje KSPP

# Ochrona uprawnien jadra
CONFIG_STRICT_KERNEL_RWX=y
CONFIG_DEBUG_WX=y

# Zabezpieczenia podsystemu bezpieczenstwa
CONFIG_SECURITY=y
CONFIG_SECURITY_YAMA=y
CONFIG_SECURITY_LANDLOCK=y
CONFIG_SECCOMP=y
CONFIG_SECCOMP_FILTER=y

# Wykrywanie uszkodzen danych
CONFIG_LIST_HARDENED=y
CONFIG_BUG_ON_DATA_CORRUPTION=y
CONFIG_SCHED_STACK_END_CHECK=y

# Wylaczenie niebezpiecznych funkcji
# CONFIG_DEVKMEM is not set
# CONFIG_PROC_KCORE is not set
# CONFIG_KEXEC is not set
# CONFIG_HIBERNATION is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_LEGACY_TIOCSTI is not set

Narzedzie kernel-hardening-checker

Do weryfikacji konfiguracji jadra sluzy doskonale narzedzie kernel-hardening-checker autorstwa Alexandra Popova. Sprawdza opcje Kconfig, parametry linii polecen jadra oraz ustawienia sysctl:

# Instalacja narzedzia
pip install kernel-hardening-checker

# Sprawdzenie biezacej konfiguracji jadra
kernel-hardening-checker -c /boot/config-$(uname -r)

# Sprawdzenie z konfiguracja z proc
kernel-hardening-checker -c /proc/config.gz

# Sprawdzenie konfiguracji jadra, linii polecen i sysctl
kernel-hardening-checker -c /boot/config-$(uname -r) \
    -l /proc/cmdline \
    -s /proc/sys/

Narzedzie wyswietla raport z zaleceniami, oznaczajac kazda opcje jako OK lub FAIL. Polecam uruchamiac je po kazdej aktualizacji jadra.

Seccomp i Seccomp-BPF — ograniczanie wywolan systemowych

Seccomp (Secure Computing Mode) to mechanizm jadra Linux pozwalajacy procesowi na ograniczenie zestawu wywolan systemowych, ktorych moze uzywac. Szczerze mowiac, to jeden z najskuteczniejszych sposobow na zmniejszenie powierzchni ataku jadra z perspektywy aplikacji.

Tryb scisly (strict mode)

W trybie scislym proces moze uzywac wylacznie czterech syscalli: read(), write(), _exit() i sigreturn(). Kazda proba uzycia innego syscalla = natychmiastowy SIGKILL. Bardzo restrykcyjne, ale przydatne dla procesow przetwarzajacych niezaufane dane.

Tryb filtrowania (filter mode) — Seccomp-BPF

Seccomp-BPF pozwala na definiowanie precyzyjnych filtrow za pomoca programow BPF. Mozna okreslic, ktore syscalle sa dozwolone, a ktore blokowane, a nawet filtrowac na podstawie argumentow wywolan systemowych. Dla kazdego syscalla dostepne sa akcje: zezwol (ALLOW), zakoncz proces (KILL), wyslij sygnal (TRAP), zwroc blad (ERRNO) lub powiadom (NOTIFY).

Sprawdzanie obslugi Seccomp

# Sprawdzenie czy jadro obsluguje seccomp
grep CONFIG_SECCOMP /boot/config-$(uname -r)
# Oczekiwany wynik:
# CONFIG_SECCOMP=y
# CONFIG_SECCOMP_FILTER=y

# Sprawdzenie statusu seccomp dla dzialajacego procesu
grep Seccomp /proc/self/status
# Seccomp:        0    (wylaczony)
# Seccomp:        1    (tryb scisly)
# Seccomp:        2    (tryb filtrowania)

# Sprawdzenie dostepnych akcji seccomp
cat /proc/sys/kernel/seccomp/actions_avail

Praktyczny przyklad filtru Seccomp-BPF w jezyku C

Ponizszy przyklad pokazuje, jak utworzyc filtr Seccomp-BPF ograniczajacy proces do minimalnego zestawu syscalli przy uzyciu biblioteki libseccomp:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <seccomp.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char *argv[]) {
    /* Inicjalizacja kontekstu seccomp
     * SCMP_ACT_KILL_PROCESS - domyslna akcja: zabij proces
     * przy probie uzycia niedozwolonego syscalla */
    scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL_PROCESS);
    if (ctx == NULL) {
        perror("seccomp_init");
        return EXIT_FAILURE;
    }

    /* Dodanie dozwolonych wywolan systemowych */
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);

    /* Zezwol na write() tylko do stdout i stderr
     * (fd == 1 lub fd == 2) */
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
        SCMP_A0(SCMP_CMP_EQ, STDOUT_FILENO));
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
        SCMP_A0(SCMP_CMP_EQ, STDERR_FILENO));

    /* Zaladowanie filtru do jadra */
    if (seccomp_load(ctx) < 0) {
        perror("seccomp_load");
        seccomp_release(ctx);
        return EXIT_FAILURE;
    }

    /* Zwolnienie kontekstu (filtr jest juz aktywny w jadrze) */
    seccomp_release(ctx);

    /* Od tego momentu proces moze uzywac tylko dozwolonych syscalli */
    printf("Filtr Seccomp aktywny. Proces jest sandboxowany.\n");

    /* Proba uzycia niedozwolonego syscalla spowoduje SIGKILL */
    /* np. fork() lub execve() zakonczy proces */

    return EXIT_SUCCESS;
}

Kompilacja i uruchomienie:

gcc -o seccomp_przyklad seccomp_przyklad.c -lseccomp
./seccomp_przyklad

Profile Seccomp w Docker i Podman

Konteneryzacja intensywnie wykorzystuje Seccomp — i dobrze. Docker domyslnie stosuje profil blokujacy okolo 44 z ponad 300 wywolan systemowych, w tym niebezpieczne operacje takie jak reboot, mount, kexec_load czy ptrace.

# Uruchomienie kontenera z domyslnym profilem seccomp
docker run --rm -it alpine sh

# Uruchomienie kontenera z wlasnym profilem seccomp
docker run --rm -it \
    --security-opt seccomp=/sciezka/do/profilu.json \
    alpine sh

# Uruchomienie BEZ seccomp (niezalecane!)
docker run --rm -it --security-opt seccomp=unconfined alpine sh

# Podman — generowanie profilu na podstawie trace'owania syscalli
sudo podman run --annotation io.containers.trace-syscall="of:/tmp/profil.json" \
    alpine sh -c "echo test"

Warto tworzyc wlasne, restrykcyjne profile seccomp dla kazdej aplikacji. Wiekszosc kontenerow potrzebuje jedynie 40-70 wywolan systemowych, podczas gdy domyslne profile zezwalaja na znacznie wiecej. Podman oferuje narzedzie oci-seccomp-bpf-hook, ktore automatycznie trace'uje syscalle uzywane przez kontener i generuje minimalny profil — to naprawde wygodne rozwiazanie.

Landlock LSM — nowszy mechanizm sandboxingu

Landlock to modul bezpieczenstwa Linux (LSM) umozliwiajacy nieuprzywilejowanym procesom tworzenie piaskownic ograniczajacych ich wlasne uprawnienia. Wprowadzony w jadrze 5.13, Landlock stanowi uzupelnienie Seccomp, oferujac kontrole dostepu do obiektow jadra zamiast filtrowania wywolan systemowych.

Czym Landlock rozni sie od Seccomp

Kluczowa roznica polega na podejsciu do bezpieczenstwa:

  • Seccomp-BPF filtruje wywolania systemowe — moze zezwolic lub zablokowac konkretne syscalle i ich argumenty. Operuje na poziomie interfejsu jadra.
  • Landlock kontroluje dostep do obiektow jadra — plikow, katalogow, gniazd sieciowych, sygnalow. Operuje na poziomie zasobow systemu operacyjnego.

W praktyce oznacza to, ze Seccomp moze zablokowac syscall open(), ale nie rozrozni, czy proces otwiera /tmp/plik.txt czy /etc/shadow. Landlock natomiast moze precyzyjnie okreslic, do ktorych plikow i katalogow proces ma dostep, niezaleznie od uzytego syscalla. To spora roznica.

Wersje ABI Landlock

Landlock rozwija sie poprzez kolejne wersje ABI, z ktorych kazda dodaje nowe mozliwosci:

  1. ABI 1 (jadro 5.13) — podstawowe prawa dostepu do systemu plikow (odczyt, zapis, wykonanie, tworzenie katalogow itp.)
  2. ABI 2 (jadro 5.19) — dodaje LANDLOCK_ACCESS_FS_REFER, kontrolujace przenoszenie i linkowanie plikow miedzy katalogami
  3. ABI 3 (jadro 6.2) — dodaje LANDLOCK_ACCESS_FS_TRUNCATE
  4. ABI 4 (jadro 6.7) — dodaje kontrole dostepu do sieci TCP (bind i connect)
  5. ABI 5 (jadro 6.10) — dodaje LANDLOCK_ACCESS_FS_IOCTL_DEV do kontrolowania operacji ioctl na urzadzeniach
  6. ABI 6 (jadro 6.12) — dodaje zakresy do ograniczania abstrakcyjnych gniazd UNIX i operacji na sygnalach

Sprawdzanie dostepnosci Landlock

# Sprawdzenie czy jadro obsluguje Landlock
grep CONFIG_SECURITY_LANDLOCK /boot/config-$(uname -r)
# Oczekiwany wynik: CONFIG_SECURITY_LANDLOCK=y

# Sprawdzenie czy Landlock jest wlaczony w LSM
cat /sys/kernel/security/lsm
# Powinien zawierac "landlock" na liscie

# Sprawdzenie wersji ABI Landlock
# (poprzez programowe wywolanie landlock_create_ruleset z NULL)

# Sprawdzenie statusu w systemie
dmesg | grep landlock

Praktyczny przyklad uzycia Landlock w jezyku C

Ponizszy przyklad pokazuje, jak utworzyc piaskownice Landlock ograniczajaca proces do odczytu z wybranego katalogu:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <linux/landlock.h>

/* Wrappery dla wywolan systemowych Landlock */
static inline int landlock_create_ruleset(
    const struct landlock_ruleset_attr *attr, size_t size, __u32 flags)
{
    return syscall(__NR_landlock_create_ruleset, attr, size, flags);
}

static inline int landlock_add_rule(
    int ruleset_fd, enum landlock_rule_type type,
    const void *attr, __u32 flags)
{
    return syscall(__NR_landlock_add_rule, ruleset_fd, type, attr, flags);
}

static inline int landlock_restrict_self(
    int ruleset_fd, __u32 flags)
{
    return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);
}

int main(void) {
    int ruleset_fd, err;

    /* Sprawdzenie wersji ABI */
    int abi = landlock_create_ruleset(NULL, 0,
        LANDLOCK_CREATE_RULESET_VERSION);
    if (abi < 0) {
        perror("Landlock nie jest dostepny");
        return EXIT_FAILURE;
    }
    printf("Landlock ABI wersja: %d\n", abi);

    /* Definicja zestawu regul — kontrola dostepu do plikow */
    struct landlock_ruleset_attr ruleset_attr = {
        .handled_access_fs =
            LANDLOCK_ACCESS_FS_READ_FILE |
            LANDLOCK_ACCESS_FS_READ_DIR |
            LANDLOCK_ACCESS_FS_EXECUTE |
            LANDLOCK_ACCESS_FS_WRITE_FILE |
            LANDLOCK_ACCESS_FS_REMOVE_FILE |
            LANDLOCK_ACCESS_FS_REMOVE_DIR |
            LANDLOCK_ACCESS_FS_MAKE_REG |
            LANDLOCK_ACCESS_FS_MAKE_DIR,
    };

    /* Utworzenie zestawu regul */
    ruleset_fd = landlock_create_ruleset(&ruleset_attr,
        sizeof(ruleset_attr), 0);
    if (ruleset_fd < 0) {
        perror("landlock_create_ruleset");
        return EXIT_FAILURE;
    }

    /* Dodanie reguly: zezwol na odczyt z /usr */
    int path_fd = open("/usr", O_PATH | O_CLOEXEC);
    if (path_fd < 0) {
        perror("open /usr");
        close(ruleset_fd);
        return EXIT_FAILURE;
    }

    struct landlock_path_beneath_attr path_attr = {
        .allowed_access =
            LANDLOCK_ACCESS_FS_READ_FILE |
            LANDLOCK_ACCESS_FS_READ_DIR |
            LANDLOCK_ACCESS_FS_EXECUTE,
        .parent_fd = path_fd,
    };

    err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
        &path_attr, 0);
    close(path_fd);
    if (err) {
        perror("landlock_add_rule");
        close(ruleset_fd);
        return EXIT_FAILURE;
    }

    /* Dodanie reguly: zezwol na odczyt i zapis w /tmp */
    path_fd = open("/tmp", O_PATH | O_CLOEXEC);
    if (path_fd < 0) {
        perror("open /tmp");
        close(ruleset_fd);
        return EXIT_FAILURE;
    }

    struct landlock_path_beneath_attr tmp_attr = {
        .allowed_access =
            LANDLOCK_ACCESS_FS_READ_FILE |
            LANDLOCK_ACCESS_FS_READ_DIR |
            LANDLOCK_ACCESS_FS_WRITE_FILE |
            LANDLOCK_ACCESS_FS_MAKE_REG,
        .parent_fd = path_fd,
    };

    err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
        &tmp_attr, 0);
    close(path_fd);
    if (err) {
        perror("landlock_add_rule /tmp");
        close(ruleset_fd);
        return EXIT_FAILURE;
    }

    /* Wlaczenie sandboxingu — ograniczenie procesu */
    prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
    err = landlock_restrict_self(ruleset_fd, 0);
    close(ruleset_fd);
    if (err) {
        perror("landlock_restrict_self");
        return EXIT_FAILURE;
    }

    printf("Landlock sandbox aktywny!\n");
    printf("Proces ma dostep tylko do /usr (odczyt) i /tmp (odczyt/zapis).\n");

    /* Proba otwarcia pliku poza sandboxem zakonczy sie bledem */
    FILE *f = fopen("/etc/passwd", "r");
    if (f == NULL) {
        perror("Dostep do /etc/passwd zablokowany przez Landlock");
    } else {
        fclose(f);
        printf("UWAGA: /etc/passwd jest dostepny — sandbox nie dziala!\n");
    }

    return EXIT_SUCCESS;
}

Kompilacja i uruchomienie:

gcc -o landlock_przyklad landlock_przyklad.c
./landlock_przyklad

Warto wiedziec, ze Landlock jest stackowalny — proces moze nakladac kolejne warstwy ograniczen, ale nigdy nie moze ich poluznic. Kazda nowa warstwa moze tylko dalej zawezac uprawnienia. To sprawia, ze mechanizm jest odporny na proby obejscia, co jest dosc eleganckim rozwiazaniem.

Monitorowanie i audyt bezpieczenstwa jadra

Hartowanie jadra to nie jednorazowe zadanie — wymaga ciaglego monitorowania. Z mojego doswiadczenia wynika, ze wiele organizacji robi pierwszy krok (implementacja), ale potem zapomina o weryfikacji. Nie powtarzajmy tego bledu.

Uzycie narzedzia kernel-hardening-checker

Jak wspomnialem wczesniej, kernel-hardening-checker to kompleksowe narzedzie do audytu konfiguracji jadra. Warto uruchamiac je regularnie, szczegolnie po aktualizacjach:

# Pelny audyt z raportem
kernel-hardening-checker -c /boot/config-$(uname -r) \
    -l /proc/cmdline \
    -s /proc/sys/ \
    2>&1 | tee /var/log/kernel-hardening-audit.log

# Filtrowanie tylko bledow (FAIL)
kernel-hardening-checker -c /boot/config-$(uname -r) | grep FAIL

# Generowanie raportu w formacie JSON
kernel-hardening-checker -c /boot/config-$(uname -r) \
    --json 2>&1 | python3 -m json.tool

Weryfikacja aktywnych parametrow sysctl

Regularne sprawdzanie, czy ustawienia sysctl sa faktycznie aktywne, to absolutna podstawa. Oto gotowy skrypt:

#!/bin/bash
# Skrypt weryfikujacy krytyczne parametry sysctl

declare -A EXPECTED_VALUES=(
    ["kernel.dmesg_restrict"]="1"
    ["kernel.kptr_restrict"]="2"
    ["kernel.yama.ptrace_scope"]="2"
    ["kernel.randomize_va_space"]="2"
    ["kernel.unprivileged_bpf_disabled"]="1"
    ["kernel.perf_event_paranoid"]="3"
    ["net.core.bpf_jit_harden"]="2"
    ["fs.suid_dumpable"]="0"
    ["fs.protected_hardlinks"]="1"
    ["fs.protected_symlinks"]="1"
    ["net.ipv4.conf.all.rp_filter"]="1"
    ["net.ipv4.tcp_syncookies"]="1"
    ["net.ipv4.conf.all.accept_redirects"]="0"
    ["net.ipv4.conf.all.accept_source_route"]="0"
    ["net.ipv4.conf.all.log_martians"]="1"
)

echo "=== Audyt parametrow sysctl ==="
FAILURES=0

for param in "${!EXPECTED_VALUES[@]}"; do
    actual=$(sysctl -n "$param" 2>/dev/null)
    expected="${EXPECTED_VALUES[$param]}"

    if [ "$actual" = "$expected" ]; then
        echo "[OK]   $param = $actual"
    else
        echo "[FAIL] $param = $actual (oczekiwano: $expected)"
        ((FAILURES++))
    fi
done

echo ""
echo "Wynik: $FAILURES niezgodnosci z ${#EXPECTED_VALUES[@]} sprawdzonych parametrow."

if [ $FAILURES -gt 0 ]; then
    echo "UWAGA: Niektore parametry wymagaja korekty!"
    exit 1
fi

Framework auditd — monitorowanie zdarzen jadra

System audytu Linux (auditd) umozliwia monitorowanie zdarzen jadra w czasie rzeczywistym. Jest nieoceniony do wykrywania prob exploitacji i naruszen polityk bezpieczenstwa:

# Instalacja auditd
sudo apt install auditd audispd-plugins    # Debian/Ubuntu
sudo dnf install audit                      # Fedora/RHEL

# Wlaczenie i uruchomienie uslugi
sudo systemctl enable --now auditd

Kluczowe reguly audytu, ktore warto wdrozyc:

# /etc/audit/rules.d/99-kernel-security.rules

# Monitorowanie zmian w modulach jadra
-w /sbin/insmod -p x -k kernel_modules
-w /sbin/rmmod -p x -k kernel_modules
-w /sbin/modprobe -p x -k kernel_modules
-a always,exit -F arch=b64 -S init_module,finit_module -k kernel_modules
-a always,exit -F arch=b64 -S delete_module -k kernel_modules

# Monitorowanie zmian w konfiguracji sysctl
-w /etc/sysctl.conf -p wa -k sysctl_changes
-w /etc/sysctl.d/ -p wa -k sysctl_changes

# Monitorowanie dostepu do wrazliwych plikow jadra
-w /boot/ -p wa -k boot_changes
-w /lib/modules/ -p wa -k module_changes

# Monitorowanie prob eskalacji uprawnien
-a always,exit -F arch=b64 -S setuid,setgid,setreuid,setregid -k privilege_escalation
-a always,exit -F arch=b64 -S execve -C uid!=euid -F euid=0 -k privilege_escalation

# Monitorowanie uzycia ptrace
-a always,exit -F arch=b64 -S ptrace -k ptrace_usage

# Monitorowanie prob modyfikacji czasu systemowego
-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time_changes

# Monitorowanie prob montowania systemow plikow
-a always,exit -F arch=b64 -S mount,umount2 -k mount_operations

Kilka przydatnych polecen do analizy logow audytu:

# Wyszukiwanie zdarzen zwiazanych z modulami jadra
sudo ausearch -k kernel_modules --start today

# Raport o probach eskalacji uprawnien
sudo ausearch -k privilege_escalation --start today

# Generowanie raportu zbiorczego
sudo aureport --summary

# Raport o anomaliach
sudo aureport --anomaly

# Monitorowanie w czasie rzeczywistym
sudo tail -f /var/log/audit/audit.log | ausearch --interpret

Monitorowanie integralnosci w czasie rzeczywistym

Oprocz auditd warto wdrozyc dodatkowe mechanizmy monitorowania integralnosci jadra:

# Sprawdzenie integralnosci modulow jadra (z podpisami)
for mod in $(lsmod | awk 'NR>1 {print $1}'); do
    modinfo "$mod" 2>/dev/null | grep -q "sig_id" && \
        echo "[SIGNED]   $mod" || \
        echo "[UNSIGNED] $mod"
done

# Monitorowanie zmian w /proc/sys/ (parametry jadra)
# Porownanie z oczekiwanym stanem
sudo sysctl -a 2>/dev/null | sort > /tmp/sysctl_current.txt
diff /etc/sysctl_baseline.txt /tmp/sysctl_current.txt

# Sprawdzenie czy Lockdown LSM jest aktywny
cat /sys/kernel/security/lockdown

Praktyczny przewodnik wdrozeniowy — krok po kroku

Teoria to jedno, ale przejdzmy do praktyki. Ponizej znajdziesz kompletny workflow hartowania jadra, ktory mozesz zastosowac w srodowisku produkcyjnym. Proces sklada sie z czterech faz.

Faza 1: Ocena stanu poczatkowego

Zanim zaczniesz cokolwiek zmieniac, dokladnie poznaj aktualny stan zabezpieczen. Znam przypadki, kiedy administratorzy wdrazali hartowanie "na slepo" i psuli dzialajace aplikacje. Nie rob tego — najpierw audyt:

#!/bin/bash
# faza1_ocena.sh — Kompleksowa ocena stanu bezpieczenstwa jadra

echo "=== FAZA 1: Ocena stanu bezpieczenstwa jadra ==="
echo "Data: $(date)"
echo "Jadro: $(uname -r)"
echo "Dystrybucja: $(cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2)"
echo ""

# 1. Uruchomienie kernel-hardening-checker
echo "--- Audyt kernel-hardening-checker ---"
if command -v kernel-hardening-checker &>/dev/null; then
    kernel-hardening-checker -c /boot/config-$(uname -r) \
        -l /proc/cmdline -s /proc/sys/ \
        2>&1 | tee /tmp/khc_report.txt
    echo ""
    echo "Podsumowanie:"
    grep -c "OK" /tmp/khc_report.txt | xargs -I{} echo "  OK: {}"
    grep -c "FAIL" /tmp/khc_report.txt | xargs -I{} echo "  FAIL: {}"
else
    echo "UWAGA: kernel-hardening-checker nie jest zainstalowany."
    echo "Instalacja: pip install kernel-hardening-checker"
fi

# 2. Sprawdzenie aktywnych LSM
echo ""
echo "--- Aktywne moduly bezpieczenstwa (LSM) ---"
cat /sys/kernel/security/lsm 2>/dev/null || echo "Brak dostepu"

# 3. Sprawdzenie statusu Seccomp
echo ""
echo "--- Status Seccomp ---"
grep CONFIG_SECCOMP /boot/config-$(uname -r) 2>/dev/null

# 4. Sprawdzenie statusu Landlock
echo ""
echo "--- Status Landlock ---"
grep CONFIG_SECURITY_LANDLOCK /boot/config-$(uname -r) 2>/dev/null

# 5. Krytyczne parametry sysctl
echo ""
echo "--- Krytyczne parametry sysctl ---"
for param in kernel.dmesg_restrict kernel.kptr_restrict \
    kernel.yama.ptrace_scope kernel.randomize_va_space \
    kernel.unprivileged_bpf_disabled net.core.bpf_jit_harden \
    fs.suid_dumpable net.ipv4.tcp_syncookies; do
    val=$(sysctl -n "$param" 2>/dev/null || echo "N/A")
    echo "  $param = $val"
done

# 6. Lista zaladowanych modulow jadra
echo ""
echo "--- Zaladowane moduly jadra ($(lsmod | wc -l) modulow) ---"
lsmod | head -20
echo "..."

echo ""
echo "=== Raport zapisano do /tmp/khc_report.txt ==="

Faza 2: Implementacja zmian sysctl

Na podstawie wynikow audytu implementujemy zmiany. Kluczowa zasada: robic to stopniowo i testowac kazda zmiane. Nie wrzucaj wszystkiego naraz na produkcje:

#!/bin/bash
# faza2_implementacja.sh — Implementacja zmian hartowania

set -euo pipefail

echo "=== FAZA 2: Implementacja hartowania jadra ==="

# Kopia zapasowa aktualnych ustawien
echo "Tworzenie kopii zapasowej aktualnych ustawien sysctl..."
sudo sysctl -a 2>/dev/null | sort > /etc/sysctl_backup_$(date +%Y%m%d).txt
echo "Kopia zapisana: /etc/sysctl_backup_$(date +%Y%m%d).txt"

# Wdrozenie pliku konfiguracyjnego
echo "Wdrazanie /etc/sysctl.d/99-hardening.conf..."
sudo cp /etc/sysctl.d/99-hardening.conf \
    /etc/sysctl.d/99-hardening.conf.bak 2>/dev/null || true

sudo tee /etc/sysctl.d/99-hardening.conf > /dev/null <<'SYSCTL'
# Automatycznie wygenerowano — hartowanie jadra Linux 2026
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
kernel.perf_event_paranoid = 3
kernel.yama.ptrace_scope = 2
kernel.randomize_va_space = 2
kernel.unprivileged_bpf_disabled = 1
net.core.bpf_jit_harden = 2
fs.suid_dumpable = 0
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_timestamps = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0
SYSCTL

echo "Zastosowanie zmian..."
sudo sysctl --system

echo "Ustawienia sysctl zastosowane pomyslnie."

Faza 3: Testowanie i walidacja

Po wprowadzeniu zmian — i to jest krok, ktorego absolutnie nie wolno pominac — nalezy zweryfikowac, ze system dziala poprawnie i zabezpieczenia sa aktywne:

#!/bin/bash
# faza3_walidacja.sh — Testowanie i walidacja hartowania

echo "=== FAZA 3: Testowanie i walidacja ==="

PASS=0
FAIL=0

test_param() {
    local param=$1
    local expected=$2
    local actual=$(sysctl -n "$param" 2>/dev/null)

    if [ "$actual" = "$expected" ]; then
        echo "[PASS] $param = $actual"
        ((PASS++))
    else
        echo "[FAIL] $param = $actual (oczekiwano: $expected)"
        ((FAIL++))
    fi
}

echo "--- Weryfikacja parametrow sysctl ---"
test_param "kernel.dmesg_restrict" "1"
test_param "kernel.kptr_restrict" "2"
test_param "kernel.yama.ptrace_scope" "2"
test_param "kernel.randomize_va_space" "2"
test_param "kernel.unprivileged_bpf_disabled" "1"
test_param "kernel.perf_event_paranoid" "3"
test_param "net.core.bpf_jit_harden" "2"
test_param "fs.suid_dumpable" "0"
test_param "fs.protected_hardlinks" "1"
test_param "fs.protected_symlinks" "1"
test_param "net.ipv4.conf.all.rp_filter" "1"
test_param "net.ipv4.tcp_syncookies" "1"
test_param "net.ipv4.conf.all.accept_redirects" "0"
test_param "net.ipv4.conf.all.accept_source_route" "0"
test_param "net.ipv4.conf.all.send_redirects" "0"
test_param "net.ipv4.conf.all.log_martians" "1"

echo ""
echo "--- Testy funkcjonalne ---"

# Test: dmesg powinien byc niedostepny dla zwyklego uzytkownika
if sudo -u nobody dmesg 2>&1 | grep -q "Operation not permitted"; then
    echo "[PASS] dmesg zablokowany dla nieuprzywilejowanych uzytkownikow"
    ((PASS++))
else
    echo "[FAIL] dmesg dostepny dla nieuprzywilejowanych uzytkownikow"
    ((FAIL++))
fi

# Test: /proc/kallsyms powinien byc ukryty
if sudo -u nobody cat /proc/kallsyms 2>&1 | grep -q "0000000000000000"; then
    echo "[PASS] Wskazniki jadra ukryte w /proc/kallsyms"
    ((PASS++))
else
    echo "[FAIL] Wskazniki jadra widoczne w /proc/kallsyms"
    ((FAIL++))
fi

echo ""
echo "=== Wyniki: $PASS testow pomyslnych, $FAIL niepowodzen ==="

if [ $FAIL -gt 0 ]; then
    echo "UWAGA: Niektore testy nie przeszly. Sprawdz konfiguracje."
    exit 1
else
    echo "Wszystkie testy pomyslne. Hartowanie jadra jest aktywne."
fi

Faza 4: Automatyzacja z Ansible

Dla srodowisk z wieloma serwerami (a kto dzis ma tylko jeden?) warto zautomatyzowac hartowanie jadra za pomoca Ansible:

# kernel_hardening.yml — Playbook Ansible do hartowania jadra
---
- name: Hartowanie jadra Linux
  hosts: all
  become: yes
  vars:
    sysctl_params:
      kernel.dmesg_restrict: 1
      kernel.kptr_restrict: 2
      kernel.perf_event_paranoid: 3
      kernel.yama.ptrace_scope: 2
      kernel.randomize_va_space: 2
      kernel.unprivileged_bpf_disabled: 1
      net.core.bpf_jit_harden: 2
      fs.suid_dumpable: 0
      fs.protected_hardlinks: 1
      fs.protected_symlinks: 1
      net.ipv4.conf.all.rp_filter: 1
      net.ipv4.conf.default.rp_filter: 1
      net.ipv4.tcp_syncookies: 1
      net.ipv4.conf.all.accept_redirects: 0
      net.ipv4.conf.default.accept_redirects: 0
      net.ipv4.conf.all.secure_redirects: 0
      net.ipv4.conf.default.secure_redirects: 0
      net.ipv4.conf.all.accept_source_route: 0
      net.ipv4.conf.default.accept_source_route: 0
      net.ipv4.conf.all.send_redirects: 0
      net.ipv4.conf.default.send_redirects: 0
      net.ipv4.conf.all.log_martians: 1
      net.ipv4.conf.default.log_martians: 1
      net.ipv4.icmp_echo_ignore_broadcasts: 1
      net.ipv4.icmp_ignore_bogus_error_responses: 1
      net.ipv4.tcp_timestamps: 0
      net.ipv6.conf.all.accept_redirects: 0
      net.ipv6.conf.default.accept_redirects: 0
      net.ipv6.conf.all.accept_source_route: 0
      net.ipv6.conf.default.accept_source_route: 0
      net.ipv6.conf.all.accept_ra: 0
      net.ipv6.conf.default.accept_ra: 0

  tasks:
    - name: Instalacja wymaganych pakietow
      package:
        name:
          - auditd
          - python3-pip
        state: present

    - name: Instalacja kernel-hardening-checker
      pip:
        name: kernel-hardening-checker
        state: present

    - name: Zastosowanie parametrow sysctl
      sysctl:
        name: "{{ item.key }}"
        value: "{{ item.value }}"
        sysctl_file: /etc/sysctl.d/99-hardening.conf
        reload: yes
        state: present
      loop: "{{ sysctl_params | dict2items }}"

    - name: Wdrozenie regul audytu
      copy:
        dest: /etc/audit/rules.d/99-kernel-security.rules
        content: |
          -w /sbin/insmod -p x -k kernel_modules
          -w /sbin/rmmod -p x -k kernel_modules
          -w /sbin/modprobe -p x -k kernel_modules
          -a always,exit -F arch=b64 -S init_module,finit_module -k kernel_modules
          -a always,exit -F arch=b64 -S delete_module -k kernel_modules
          -w /etc/sysctl.conf -p wa -k sysctl_changes
          -w /etc/sysctl.d/ -p wa -k sysctl_changes
          -a always,exit -F arch=b64 -S setuid,setgid,setreuid,setregid -k priv_esc
          -a always,exit -F arch=b64 -S ptrace -k ptrace_usage
        mode: '0640'
      notify: restart auditd

    - name: Uruchomienie audytu kernel-hardening-checker
      command: >
        kernel-hardening-checker
        -c /boot/config-{{ ansible_kernel }}
      register: khc_result
      changed_when: false
      failed_when: false

    - name: Zapisanie raportu audytu
      copy:
        content: "{{ khc_result.stdout }}"
        dest: "/var/log/kernel-hardening-audit-{{ ansible_date_time.date }}.log"
        mode: '0640'

    - name: Wyswietlenie podsumowania
      debug:
        msg: >
          Hartowanie jadra zastosowane na {{ inventory_hostname }}.
          Parametry sysctl: {{ sysctl_params | length }} ustawionych.
          Raport: /var/log/kernel-hardening-audit-{{ ansible_date_time.date }}.log

  handlers:
    - name: restart auditd
      service:
        name: auditd
        state: restarted

Uruchomienie playbooka:

# Na wszystkich serwerach
ansible-playbook -i inventory kernel_hardening.yml

# Tryb sprawdzania (dry-run) — bez wprowadzania zmian
ansible-playbook -i inventory kernel_hardening.yml --check --diff

# Na wybranej grupie serwerow
ansible-playbook -i inventory kernel_hardening.yml --limit webservers

Podsumowanie — podejscie obrony w glebokosci

Hartowanie jadra Linux w 2026 roku nie jest jednorazowym zadaniem, lecz ciaglym procesem wymagajacym wielowarstwowego podejscia — tak zwanej obrony w glebokosci (defense in depth). Zadna pojedyncza technika nie zapewni pelnej ochrony, ale ich kombinacja tworzy solidna bariere nawet przeciwko zaawansowanym zagrozeniom.

Podsumowujac kluczowe elementy tego przewodnika:

  1. Parametry sysctl — pierwsza, najlatwiejsza do wdrozenia linia obrony. Ograniczenie dostepu do informacji o jadrze, wzmocnienie ASLR i utwardzanie stosu sieciowego powinno byc standardem na kazdym serwerze.
  2. Opcje kompilacji jadra (KSPP) — gleboka ochrona na poziomie kodu, od stack canaries po inicjalizacje pamieci przy alokacji i zwolnieniu.
  3. Seccomp-BPF — drastyczne zmniejszenie powierzchni ataku jadra poprzez ograniczenie dostepnych syscalli. W kontenerach absolutnie niezbedny.
  4. Landlock LSM — precyzyjna kontrola dostepu do obiektow jadra, uzupelniajaca Seccomp o sandboxing na poziomie zasobow.
  5. Monitorowanie i audyt — ciagla weryfikacja stanu zabezpieczen za pomoca kernel-hardening-checker, auditd i skryptow walidacyjnych.
  6. Automatyzacja — spojnosc konfiguracji w calej infrastrukturze dzieki Ansible lub podobnym narzediom.

W obliczu ponad 5500 CVE jadra rocznie i grup ransomware aktywnie wykorzystujacych exploity jadra, hartowanie nie jest juz opcjonalne. Kazda organizacja korzystajaca z Linuksa — od startupu po korporacje — powinna traktowac bezpieczenstwo jadra jako krytyczny element swojej strategii cyberbezpieczenstwa.

Pamietaj o regularnym aktualizowaniu jadra do najnowszych wersji LTS, sledzeniu biuletynow bezpieczenstwa swojej dystrybucji i ponownym uruchamianiu audytu po kazdej zmianie konfiguracji. Bezpieczenstwo to proces, nie stan — a jadro systemu operacyjnego jest jego fundamentem.

O Autorze Editorial Team

Our team of expert writers and editors.