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.
