SELinux (Security-Enhanced Linux) je bezpečnostní vrstva navíc nad klasickými právy. Běžná práva (kdo smí číst/zapisovat soubor) říkají, co komu patří. SELinux přidává politiku, která říká co která služba vůbec smí dělat — a platí i na roota. Když ti hackeři prolomí webserver, klasická práva mu možná dovolí sáhnout kam nemá; SELinux ho drží v ohrádce, ze které nesmí ven. Na distribucích z rodiny RHEL (Fedora, RHEL, Rocky, CentOS…) je zapnutý defaultně, takže se s ním dřív nebo později setkáš (Ubuntu a Debian mají obdobný AppArmor). Lepší je mu rozumět než ho vypínat.
Pár pojmů na úvod
- DAC (Discretionary Access Control) = klasická unixová práva (
rwx, vlastník, skupina). Rozhoduje o nich vlastník souboru — komu chce, tomu dá přístup. Root je nad tím vším a smí prakticky cokoli. - MAC (Mandatory Access Control) = to, co přidává SELinux. Pravidla určuje centrální politika, ne vlastník, a nejde je obejít — omezuje i roota. Proto „mandatory" (povinné, vynucené).
- Kontext (label) = štítek nalepený na každém souboru a procesu ve tvaru
user:role:type:level. Podle něj politika rozhoduje. Nejdůležitější je type. - Politika (policy) = sada pravidel „proces typu X smí sáhnout na soubor typu Y". Obvyklá je tzv. targeted policy — hlídá hlavně síťové služby (webserver, DB…), běžné uživatele nechává být.
- AVC denial = záznam v logu „SELinux tohle zakázal". Když něco záhadně nejde, hledáš právě tohle.
DAC vs MAC — proč práva navíc
Představ si webserver httpd, který běží pod uživatelem apache. Klasická práva (DAC) mu dovolí číst
všechno, na co má apache právo. Když ale někdo zneužije chybu v serveru, získá přesně tahle práva —
a může začít šmejdit po systému, číst cizí konfiguráky, otevírat síťová spojení.
SELinux (MAC) přidá druhý zámek: webserver běží jako proces typu httpd_t a politika mu dovolí
sáhnout jen na soubory typu httpd_sys_content_t, poslouchat jen na povolených portech a nic víc. I
kdyby útočník server ovládl, pořád je uvězněný v tom, co smí httpd_t — ke zbytku systému se nedostane.
💡 Klíčová věta: DAC ověří „patří ti to?", MAC ověří „smíš to ty vůbec dělat?". Přístup projde, jen když ho povolí oba. SELinux nikdy nepřidává práva navíc — jen ubírá.
Režimy: enforcing, permissive, disabled
SELinux umí běžet ve třech režimech:
- enforcing — politika se vynucuje: co je zakázané, se zablokuje a zapíše do logu. Normální stav.
- permissive — politika se nevynucuje, ale porušení se loguje. Nic neblokuje — slouží k ladění: necháš appku běžet, posbíráš, co všechno by SELinux zakázal, a opravíš to. Ochrana je ale vypnutá.
- disabled — SELinux úplně mimo. Žádné labely, žádná ochrana. Nedělej to.
getenforce # vypíše aktuální režim (Enforcing / Permissive / Disabled)
sudo setenforce 0 # dočasně přepni na permissive (do rebootu)
sudo setenforce 1 # zpět na enforcing
Trvalé nastavení je v /etc/selinux/config (řádek SELINUX=enforcing). Změna režimu z/na disabled
vyžaduje reboot (systém musí soubory přeznačkovat), přepnutí enforcing ↔ permissive jde za běhu.
🚩 Permissive je nástroj na ladění, ne cílový stav. Když něco nejde, přepni dočasně na permissive, ověř, jestli za to může SELinux (najednou to jede?), posbírej denials a oprav kontext. Pak zpět na enforcing. Nechat systém natrvalo v permissive/disabled = zahodíš celou vrstvu ochrany, kvůli které tam je.
Kontext (label): co je na souboru napsané
Kontext uvidíš přepínačem -Z — funguje u spousty nástrojů:
ls -Z /var/www/html # kontext souborů
ps -Z # kontext procesů
id -Z # kontext tvého shellu
Výstup vypadá třeba takhle:
system_u:object_r:httpd_sys_content_t:s0 index.html
Rozklad user:role:type:level:
- user (
system_u) — SELinux uživatel (není totéž co unixový účet), zřídka řešíš. - role (
object_r) — role, u souborů skoro vždyobject_r. - type (
httpd_sys_content_t) — tohle je to podstatné. Podle typu politika rozhoduje. Typy poznáš podle koncovky_t. - level (
s0) — úroveň pro MLS/MCS (víceúrovňová bezpečnost), na desktopu/serveru většinous0.
💡 V 95 % případů tě zajímá jen type. Když ti webserver nečte soubor, skoro vždy je to tím, že soubor má špatný type — a proces typu
httpd_tna něj podle politiky nesmí.
restorecon, semanage, chcon — jak měnit kontext
Tři nástroje, snadno se pletou. Rozdíl je zásadní:
restorecon — nastaví soubor na správný kontext podle politiky. Politika ví, jaký kontext
má mít soubor na daném místě (např. cokoli v /var/www/html → httpd_sys_content_t). Tohle je tvoje
každodenní záchrana:
sudo restorecon -Rv /var/www/html # -R rekurzivně, -v ukáže, co změnil
semanage fcontext — přidá trvalé pravidlo do politiky: „soubory tady mají mít tenhle typ".
Používáš, když děláš appku na netypickém místě (třeba web v /srv/web). Nejdřív pravidlo, pak restorecon:
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/web(/.*)?"
sudo restorecon -Rv /srv/web
chcon — změní kontext dočasně a ručně. Rychlé, ale nepřežije restorecon ani relabel
systému — politika o té změně neví, takže ji dřív nebo později přepíše. Dobré na rychlý test, ne na trvalo:
sudo chcon -t httpd_sys_content_t soubor.html # jen dočasně!
🚩 Pořadí důležitosti:
restorecon(oprav podle politiky) →semanage(uč politiku nové místo) →chcon(jen dočasný test). Když použiješchcona myslíš, že máš hotovo, prvnírestorecon(nebo automatický relabel) ti to potichu vrátí zpátky.
Booleans: přepínače politiky
Někdy nechceš měnit labely, ale zapnout schopnost, kterou politika defaultně zakazuje. Na to slouží booleans — pojmenované přepínače on/off. Třeba „smí webserver navazovat odchozí síťová spojení?" je defaultně vypnuté (kvůli bezpečnosti), a když ho appka potřebuje (volá cizí API), zapneš boolean:
getsebool -a # vypiš všechny booleans a jejich stav
getsebool httpd_can_network_connect # stav jednoho
sudo setsebool -P httpd_can_network_connect on # zapni TRVALE (-P = persistent)
💡 Nezapomeň na
-P! Bez něj se boolean vrátí po rebootu do původního stavu a „už to zase nejde".-Pzapíše změnu natrvalo do politiky.
Booleans jsou elegantní: místo psaní vlastních pravidel jen zapneš předpřipravený scénář, který autoři
politiky očekávali. Než začneš vyrábět vlastní pravidla přes audit2allow, vždycky se podívej, jestli
na to není hotový boolean.
Ladění: když něco záhadně nejde
Typický příznak SELinuxu: appka funguje „skoro", ale nějaká akce tiše selže — 403 z webu, „permission denied" tam, kde práva (DAC) vypadají v pořádku. SELinux totiž akci zablokuje a zapíše AVC denial do audit logu. Postup:
# 1) najdi denials v audit logu
sudo ausearch -m avc -ts recent
# 2) čitelné vysvětlení + doporučení (balík setroubleshoot-server)
sudo sealert -a /var/log/audit/audit.log
sealert (ze setroubleshoot) je nejpřívětivější: řekne ti lidsky, co bylo zakázáno a co s tím —
často rovnou navrhne správný restorecon nebo boolean. Na desktopu ti denial i vyskočí jako notifikace.
audit2allow umí z denialu vygenerovat vlastní pravidlo (modul politiky), které to povolí:
sudo ausearch -m avc -ts recent | audit2allow -M mojePravidlo
# sudo semodule -i mojePravidlo.pp # teprve tohle ho nainstaluje
🚩
audit2allowpoužívej opatrně a až jako poslední možnost. Slepě povolit každý denial znamená potichu odbourat přesně tu ochranu, kvůli které SELinux existuje. Nejdřív se ptej proč to bylo zakázáno: nemá soubor jen špatný kontext (→restorecon)? Není na to boolean (→setsebool)? Vlastní pravidlo dělej, až když víš, že přístup je legitimní a jinak to nejde.
Failure modes — časté omyly
- Vypnu SELinux, ať mám klid. Nejčastější reflex — a nejhorší. Vypnutím (
setenforce 0natrvalo nebodisabled) neopravíš příčinu, jen zahodíš celou bezpečnostní vrstvu. Skoro vždy jde o špatný kontext souboru, což je práce na jedenrestorecon. Řeš příčinu, ne symptom. - Přesunul jsem soubor přes
mva služba ho nečte.mvzachová původní kontext souboru z místa, odkud pochází (třebauser_home_tz domovské složky). Na novém místě má mít jiný typ, alemvho nezmění → služba na něj podle politiky nesmí. Oprava:restoreconna cíl. Naopakcpnovému souboru přiřadí kontext podle cílové složky — protocpčasto „prostě funguje" amvne. - Použil jsem
chcona za týden to zase nejde.chconje dočasná ruční změna, o které politika neví. Prvnírestoreconnebo relabel systému (např. po velké aktualizaci) ji přepíše zpět. Na trvalé řešení patřísemanage fcontext+restorecon. - Spustil jsem
audit2allowna všechno. Vygenerovat pravidlo, které povolí každý denial, je jako vytrhnout baterku z hlásiče kouře, protože pípá. Klidně tím povolíš i to, co se snažil zablokovat útok. Vždy nejdřív pochop denial: kontext / boolean / až pak vlastní pravidlo. - Zapomněl jsem
-Pusetsebool. Změna funguje do rebootu a pak „záhadně" zmizí. Trvalé změny booleanů dělej s-P.
🛠️ Cvičení
- Podívej se na labely. Vypiš SELinux kontext souborů ve
/var/www/htmla kontext běžících procesů. Najdi u nějaké síťové služby (třebasshdnebohttpd) její type a popiš, kterou částuser:role:type:levelbys řešil nejčastěji a proč. - Enforcing vs permissive. Zjisti aktuální režim, dočasně přepni na permissive a zase zpět na
enforcing. Kde je trvalé nastavení a proč přechod na/z
disabledvyžaduje reboot? - Rozbij a oprav kontext. Vytvoř soubor v domovské složce, přesuň ho přes
mvdo/var/www/htmla porovnej jeho kontext (ls -Z) s ostatními soubory tam. Pak ho oprav správným nástrojem. Který to je? - Najdi a použij boolean. Vypiš všechny booleans a najdi ten, který povolí webserveru navazovat odchozí síťová spojení. Jak ho zapneš tak, aby přežil reboot?
- Přečti denial. Najdi v audit logu poslední AVC denials (
ausearch -m avc). Vyber jeden a popiš: který proces (type), na jaký objekt (type) a jakou akci se pokoušel — a jak bys zjistil, čím to opravit.
Náčrt řešení — rozbal, až si cvičení zkusíš sám
- Labely —
ls -Z /var/www/html(kontext souborů),ps -Znebops -eZ | grep sshd(kontext procesů). Usshduvidíš typesshd_t, u webuhttpd_t. Řešíš skoro výhradně type — podle něj politika rozhoduje;user/role/levelna běžném serveru měníš zřídka. Pozor: type poznáš podle koncovky_t. - Režimy —
getenforceukáže stav,sudo setenforce 0→ permissive,sudo setenforce 1→ enforcing (obojí za běhu, do rebootu). Trvale v/etc/selinux/config(SELINUX=). Přechod na/zdisabledchce reboot, protože při vypnutém SELinuxu se soubory nelabelují — po zapnutí je systém musí celé přeznačkovat (relabel při bootu). Pozor: enforcing ↔ permissive jde za běhu, disabled ne. - mv zachová kontext — nový soubor v domově má type
user_home_t(neboadmin_home_t); pomvdo/var/www/htmlsi tenhle type ponese s sebou, kdežto sousední soubory majíhttpd_sys_content_t. Webserver (httpd_t) nauser_home_tnesmí → 403. Oprava:sudo restorecon -v soubor(nastaví kontext podle politiky). Pozor:cpby rovnou dostal správný type podle cílové složky — problém dělá hlavněmv. - Boolean —
getsebool -a | grep httpda najdešhttpd_can_network_connect. Zapnout trvale:sudo setsebool -P httpd_can_network_connect on. Bez-Pse to po rebootu vrátí. Pozor: než píšeš vlastní pravidlo přesaudit2allow, vždy hledej hotový boolean. - Denial —
sudo ausearch -m avc -ts recentvypíše řádky sescontext=(source = proces, jeho type),tcontext=(target = objekt, jeho type) a{ ... }(zakázaná akce, např.read,open,name_connect). Čitelně to rozeberesudo sealert -a /var/log/audit/audit.loga rovnou navrhne řešení (častorestoreconnebo boolean). Pozor: nejdřív pochop, PROČ byl přístup zakázán —audit2allowaž jako poslední možnost.
🧠 Otázky & odpovědi
Jaký je rozdíl mezi klasickými právy a SELinuxem?
Klasická práva jsou DAC (Discretionary Access Control) — o přístupu rozhoduje vlastník souboru přes
rwx a root je nad vším. SELinux přidává MAC (Mandatory Access Control): pravidla určuje centrální
politika, nejde je obejít a omezují i roota. Rozdíl v jedné větě — DAC řeší co komu patří, MAC řeší
co která služba vůbec smí dělat. Přístup projde jen tehdy, když ho povolí oba. SELinux nikdy nepřidává
práva navíc, jen ubírá, takže i prolomená služba zůstane uvězněná v tom, co jí politika dovolí.
Proč se nemá SELinux vypínat, když něco nejde?
Protože vypnutím neopravíš příčinu, jen zahodíš celou bezpečnostní vrstvu. V drtivé většině případů jde
jen o špatný kontext souboru — což je práce na jeden restorecon. Když opravdu potřebuješ ladit, přepni
dočasně na permissive (setenforce 0): SELinux pak nic neblokuje, ale loguje, co by zakázal. Posbíráš
denials, opravíš kontext nebo zapneš boolean a vrátíš se na enforcing. Permissive je nástroj na ladění,
ne cílový stav — disabled natrvalo znamená, že jsi zbytečně zbavil ochrany, kvůli které tam SELinux je.
Co je kontext a která jeho část je nejdůležitější?
Kontext (label) je štítek na každém souboru a procesu ve tvaru user:role:type:level — uvidíš ho
přepínačem -Z (ls -Z, ps -Z). Politika podle něj rozhoduje, kdo smí na co. Zdaleka nejdůležitější
je type (koncovka _t, třeba httpd_sys_content_t u webových souborů, httpd_t u procesu
webserveru). V praxi skoro každý SELinux problém je o tom, že soubor má špatný type a proces na něj podle
politiky nesmí. user, role a level na běžném serveru řešíš jen výjimečně.
Proč soubor přesunutý přes mv služba nepřečte, ale přes cp ano?
Protože mv zachová původní kontext souboru — přinese si type z místa, odkud pochází (třeba
user_home_t z domovské složky). Na novém místě má mít jiný type, ale mv ho nemění, takže služba
(např. httpd_t) na něj podle politiky nesmí. Naproti tomu cp vytvoří nový soubor, který dostane
kontext podle cílové složky — proto „prostě funguje". Oprava po mv je jednoduchá: restorecon
na soubor nastaví správný kontext podle politiky.
K čemu jsou booleans a proč nezapomenout na -P?
Booleans jsou pojmenované přepínače politiky (on/off), kterými zapneš nebo vypneš celý předpřipravený
scénář — třeba httpd_can_network_connect povolí webserveru odchozí síťová spojení, která jsou defaultně
zakázaná. Vypíšeš je getsebool -a, nastavíš setsebool. Přepínač -P znamená persistent — zapíše
změnu natrvalo do politiky. Bez -P funguje boolean jen do rebootu a pak „záhadně" zmizí. Booleans jsou
lepší volba než psát vlastní pravidla přes audit2allow — pokud na tvůj případ boolean existuje, použij ho.
