SELinux Praxis

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen

SELinux – Grundlagen und Praxis

Kein Vollkurs, sondern das Rüstzeug, mit dem ein Admin im Alltag klarkommt: was SELinux macht, wie es entscheidet, und welche Befehle man wirklich braucht.

Grundkonzept: DAC vs. MAC

Klassische Unix-Rechte (DAC – Discretionary Access Control)
  • Der Besitzer einer Datei entscheidet über Zugriffsrechte (rwx, Owner/Group/Other)
  • Läuft ein Prozess als root, kann er alles – DAC schützt nicht gegen kompromittierte Root-Prozesse
SELinux (MAC – Mandatory Access Control)
  • Zugriffsregeln werden zentral vom System vorgegeben, nicht vom Dateibesitzer
  • Selbst root-Prozesse sind an die Policy gebunden
  • Prinzip: Alles ist verboten, außer explizit erlaubt (Whitelist-Ansatz)

Merksatz: DAC fragt "Wem gehört die Datei?", MAC fragt "Darf dieser Prozesstyp auf diesen Ressourcentyp zugreifen?" – unabhängig vom Besitzer.

Die drei Modi

Modus Verhalten
enforcing Regeln werden durchgesetzt, Verstöße blockiert und geloggt
permissive Verstöße werden nur geloggt, aber nicht blockiert – Standard für Troubleshooting
disabled SELinux komplett aus (Reboot nötig zum Aktivieren)
# aktuellen Modus anzeigen
getenforce

# temporär umschalten (bis zum Reboot)
setenforce 0    # permissive
setenforce 1    # enforcing

# dauerhaft in /etc/selinux/config
SELINUX=enforcing

Security Context – das Herzstück

Jede Datei, jeder Prozess, jeder Port hat einen Kontext im Format:

user:role:type:level

Für die tägliche Praxis relevant ist fast ausschließlich das type-Feld – dieses Prinzip heißt Type Enforcement (TE) und ist der Mechanismus, der 95% der Alltagsprobleme verursacht bzw. löst.

graph LR A[Prozess mit Domain-Type<br/>z.B. httpd_t] -->|darf zugreifen auf| B[Datei mit Type<br/>z.B. httpd_sys_content_t] A -.->|blockiert, wenn Type nicht erlaubt| C[Datei mit Type<br/>z.B. user_home_t]

Kontexte anzeigen
  • ls -Z /var/www/html – Dateikontexte
  • ps -Z bzw. ps auxZ – Prozesskontexte
  • id -Z – eigener Kontext

Wie eine Zugriffsentscheidung getroffen wird

flowchart TD Start[Prozess versucht Zugriff] --> DAC{DAC-Check<br/>klassische Unix-Rechte} DAC -->|verweigert| Deny1[Zugriff verweigert] DAC -->|erlaubt| MAC{SELinux Policy-Check<br/>Type Enforcement} MAC -->|Regel erlaubt Zugriff| Allow[Zugriff gewährt] MAC -->|keine Regel vorhanden| Mode{Modus?} Mode -->|enforcing| Deny2[Zugriff verweigert + AVC-Log] Mode -->|permissive| Allow2[Zugriff gewährt + AVC-Log]

Wichtig: SELinux greift immer erst nach den klassischen DAC-Checks. Beide Ebenen müssen zustimmen.

Die häufigste Fehlerquelle: falscher Kontext nach Datei-Operationen

Wird eine Datei kopiert, verschoben oder neu angelegt, bekommt sie oft den falschen Kontext (z. B. Datei aus dem Home-Verzeichnis nach /var/www/html kopiert, behält aber user_home_t).

# Kontext auf den in der Policy definierten Standard zurücksetzen
restorecon -Rv /var/www/html

# Kontext temporär manuell setzen (geht bei restorecon verloren!)
chcon -t httpd_sys_content_t /var/www/html/index.html

# Kontext DAUERHAFT in der Policy-Datenbank hinterlegen (übersteht restorecon)
semanage fcontext -a -t httpd_sys_content_t "/var/www/html(/.*)?"
restorecon -Rv /var/www/html

Merksatz: chcon = Pflaster, geht beim nächsten restorecon verloren. semanage fcontext = dauerhafte Regel, danach restorecon anwenden, damit sie greift.

Booleans – Verhalten umschalten ohne eigene Policy

Booleans sind vorgefertigte Schalter für häufige Szenarien (z. B. darf Apache auf Netzwerk-Freigaben zugreifen?).

# alle Booleans mit Beschreibung auflisten
getsebool -a
semanage boolean -l

# einen Boolean dauerhaft setzen
setsebool -P httpd_can_network_connect on

Wichtig: Ohne -P gilt die Änderung nur bis zum Reboot.

Troubleshooting-Workflow

flowchart LR A[Zugriff schlägt fehl] --> B[AVC-Denial im Log suchen] B --> C[ausearch -m avc -ts recent] C --> D[audit2allow -w -a<br/>Klartext-Erklärung] D --> E{Regel sinnvoll?} E -->|ja, Standardfall| F[Boolean oder semanage fcontext nutzen] E -->|nein, Spezialfall| G[Eigenes Modul bauen]

Logs durchsuchen
  • ausearch -m avc -ts recent – aktuelle AVC-Denials
  • ausearch -m avc -ts today – alle Denials von heute
  • sealert -a /var/log/audit/audit.log – lesbare Erklärung inkl. Lösungsvorschlag (falls setroubleshoot installiert)

Eigene Module bauen

Wenn kein passender Boolean existiert und semanage fcontext nicht ausreicht (z. B. eigene Anwendung mit ungewöhnlichem Zugriffsmuster):

# 1. Denials sammeln (im permissive-Modus testen, damit nichts blockiert wird)
setenforce 0
# Anwendung normal nutzen, alle Denials provozieren

# 2. Aus den Denials ein Modul generieren lassen
ausearch -m avc -ts recent | audit2allow -M meinmodul

# 3. Erzeugtes .te-File VOR dem Laden prüfen und ggf. per Hand kürzen
cat meinmodul.te

# 4. Modul kompilieren und laden
semodule -i meinmodul.pp

# 5. zurück auf enforcing und testen
setenforce 1
Bestehende Module verwalten
  • semodule -l – geladene Module auflisten
  • semodule -r meinmodul – Modul entfernen
  • semodule -i meinmodul.pp – Modul (neu) laden

Praxis-Hinweis: audit2allow generiert oft zu großzügige Regeln (nimmt jede geloggte Aktion als "erlauben"). Das .te-File vor dem Laden immer durchsehen und unnötige allow-Zeilen streichen – sonst hebelt man den Sinn von SELinux graduell aus.

Kontext bei Nicht-Standard-Ports

Läuft ein Dienst auf einem Port, der nicht in der Policy hinterlegt ist (z. B. Apache auf Port 8080 statt 80/443):

# aktuelle Port-Zuordnungen anzeigen
semanage port -l | grep http

# neuen Port zu einem bestehenden Type hinzufügen
semanage port -a -t http_port_t -p tcp 8080

Kurzreferenz der wichtigsten Befehle

Befehl Zweck
getenforce / setenforce aktuellen Modus anzeigen / temporär ändern
ls -Z / ps -Z Datei-/Prozesskontext anzeigen
restorecon -Rv Kontext auf Policy-Standard zurücksetzen
chcon -t Kontext temporär setzen (übersteht restorecon nicht)
semanage fcontext -a Kontext-Regel dauerhaft in Policy-DB eintragen
getsebool -a / setsebool -P Booleans anzeigen / dauerhaft setzen
ausearch -m avc AVC-Denials im Audit-Log suchen
audit2allow aus Denials eine Regel/Modul generieren
semodule -i/-l/-r eigenes Modul laden/auflisten/entfernen
semanage port -a Port einem Type zuordnen