Auf AlmaLinux, Rocky Linux und anderen RHEL-basierten Systemen ist SELinux (Security-Enhanced Linux) standardmäßig aktiviert. Zusätzlich zu den üblichen Dateiberechtigungen (siehe: Dateiberechtigungen (chmod, chown) unter Linux) weist es jeder Datei, jedem Prozess und jedem Port ein Sicherheitslabel (Kontext) zu und lässt nur das zu, was die Richtlinien ausdrücklich erlauben. Wird beispielsweise der Webserver gehackt, verhindert SELinux, dass der Angreifer im Namen des Webservers auf andere Teile des Systems zugreifen kann.
Dies hat zur Folge, dass von den Standard-Einstellungen abweichende Konfigurationen (eigenes Webverzeichnis, nicht standardmäßiger Port, ausgehende Verbindungen des Webservers) den Fehler „Permission denied“ auslösen können, selbst wenn die chmod- und chown-Einstellungen korrekt sind. In solchen Fällen deaktivieren viele Nutzer SELinux, obwohl der Fehler in der Regel mit einem einzigen Befehl behoben werden kann.
Ubuntu und Debian verwenden nicht SELinux, sondern AppArmor; dort trifft dieser Artikel nicht zu. Auf cPanel-Servern muss SELinux deaktiviert sein, da cPanel dies nicht unterstützt.
Ist die Funktion aktiviert?
getenforce
sestatus
Enforcing(Durchsetzung): SELinux ist aktiv und blockiert regelwidrige Vorgänge.Permissive: Verstöße werden lediglich protokolliert, jedoch nicht gesperrt.- „
Disabled“: ist deaktiviert.
Ist SELinux die Ursache für den Fehler?
SELinux protokolliert jede Sperrung als AVC-Meldung. Die letzten Sperrungen:
sudo ausearch -m AVC -ts recent
Sollte gleichzeitig mit dem Fehler hier eine Zeile mit dem Vermerk „denied“ erscheinen, wird der Fehler durch SELinux verursacht. Ein typischer Eintrag:
type=AVC msg=audit(...): avc: denied { read } for pid=1234 comm="httpd"
name="index.html" scontext=system_u:system_r:httpd_t:s0
tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file
Daraus lässt sich ableiten, dass der Webserver (httpd_t) die Datei „index.html“ nicht lesen konnte, da deren Tag „admin_home_t“ lautet (sie wurde im Stammverzeichnis erstellt).
ausearch liest das Protokoll nur dann automatisch ein, wenn Sie es über das Terminal ausführen. Geben Sie bei der Ausführung über ein Skript oder einen Cron-Job zusätzlich den Schalter --input-logs an (sudo ausearch --input-logs -m AVC -ts recent), andernfalls liest das Programm die Standardeingabe ein und gibt die Antwort <no matches> zurück. -ts recent bezieht sich auf die letzten 10 Minuten.
Als schnellen Test können Sie vorübergehend in den toleranten Modus wechseln; wenn der Fehler dadurch behoben wird, wurde er mit Sicherheit durch SELinux verursacht:
sudo setenforce 0 # Permissive
# ... próbálja ki újra ...
sudo setenforce 1 # vissza Enforcing módba
Das Programm „audit2why“ erläutert die Gründe für Sperrungen auch in verständlicher Sprache:
sudo ausearch -m AVC -ts recent | audit2why
Die folgenden Befehle „semanage“, „audit2why“ und „audit2allow“ sind im Paket „policycoreutils-python-utils-python-utils“ enthalten:
sudo dnf install policycoreutils-python-utils
1. Fehlerhafte Dateinamen
Der häufigste Fall: Eine Datei wurde an anderer Stelle erstellt (beispielsweise im Verzeichnis „/root“ oder „/home“) und anschließend mit dem Befehl „mv“ in das Webverzeichnis verschoben. Der Befehl „mv“ behält den ursprünglichen Dateinamen bei, sodass der Webserver die Datei nicht lesen kann. (Der Befehl „cp“ weist der Kopie den Dateinamen des Zielverzeichnisses zu.)
Tags anzeigen:
ls -Z /var/www/html
Zurücksetzen der Tags auf die Standardeinstellungen:
sudo restorecon -Rv /var/www/html
Auf einem Testrechner mit AlmaLinux 10 führte die Datei „index.html“, die im Verzeichnis „/root“ erstellt und anschließend mit dem Befehl „mv“ in das Webverzeichnis verschoben wurde, zu einem 403-Fehler. Im Protokoll war die Zugriffsverweigerung vermerkt, und nach dem Befehl „restorecon“ wurde die Seite mit dem Statuscode 200 geladen:
Eigenes Webverzeichnis
Sollte sich die Website nicht unter „/var/www“ befinden (z. B. unter „/srv/www“), legen Sie SELinux fest, dass es sich hierbei ebenfalls um Webinhalte handelt, und nehmen Sie anschließend folgende Kennzeichnungen vor:
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"
sudo restorecon -Rv /srv/www
Für jene Verzeichnisse, in die die Webanwendung auch schreiben muss (Uploads, Cache), stellen Sie bitte die Option „Schreibbar“ ein:
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/wp-content/uploads(/.*)?"
sudo restorecon -Rv /var/www/html/wp-content/uploads
Die Tags können auch mit dem Befehl „chcon“ geändert werden, jedoch geht das so festgelegte Tag nach dem nächsten „restorecon“ oder einer vollständigen Neuvergabe von Tags verloren; für eine dauerhafte Einstellung ist „semanage fcontext“ die richtige Methode.
2. Logische Operatoren (Boolesche Operatoren)
Viele gängige Anforderungen lassen sich über die SELinux-Schalter erfüllen. Die Schalter für den Webserver lauten:
getsebool -a | grep httpd
Am häufigsten werden folgende Funktionen benötigt:
| Weiterleitung | Wann ist dies erforderlich? |
|---|---|
httpd_can_network_connect |
PHP stellt eine externe Verbindung her (API-Aufrufe, cURL) oder leitet als Nginx-/Apache-Proxy Daten an eine Anwendung weiter (Node.js, Python) |
httpd_can_network_connect_db |
PHP ist mit einer Datenbank verbunden, die sich auf einem anderen Server befindet |
httpd_can_sendmail |
PHP versendet E-Mails mit der Funktion „mail()“ |
httpd_unified |
Der Webserver kann auch alle Webinhalte schreiben (bequem, aber weniger sicher) |
Dauerhaft aktivieren (ohne den Parameter -P wird die Einstellung beim Neustart zurückgesetzt):
sudo setsebool -P httpd_can_network_connect on
Im Test versuchte ein PHP-Skript, mithilfe von cURL auf eine externe HTTPS-Seite zuzugreifen. Bei deaktiviertem Schalter (httpd_can_network_connect --> off, dies ist der Standardwert) gab cURL den Fehler 7 aus („Failed to connect to … port 443 … Could not connect to server“); nach der Aktivierung lautete die Antwort 200. In WordPress wird dies als Meldung „cURL-Fehler 7“ angezeigt (siehe: cURL-Fehler 28 und 60 in WordPress).
3. Nicht standardmäßige Ports
Wenn Sie einen Dienst nicht auf seinem Standardport ausführen, müssen Sie dies auch SELinux mitteilen. Das häufigste Beispiel ist die Änderung des SSH-Ports (siehe: Sicherheitseinstellungen für den SSH-Server): Wenn Sie dies versäumen, startet der „sshd“-Dienst nach einem Neustart nicht und Sie können sich möglicherweise vom Server aussperren.
sudo semanage port -a -t ssh_port_t -p tcp 2255
Bei einem Webserver (beispielsweise 8888 statt 8080):
sudo semanage port -a -t http_port_t -p tcp 8888
Die bereits freigegebenen Ports: sudo semanage port -l | grep -E "ssh|http".
4. Sonderregel, falls andere Lösungen nicht helfen
Sollte keine der oben genannten Lösungen helfen, erstellt „audit2allow“ aus den protokollierten Sperrungen ein individuelles Regelmodul:
sudo ausearch -m AVC -ts recent | audit2allow -M sajat_szabaly
sudo semodule -i sajat_szabaly.pp
Bitte überprüfen Sie vor der Installation die erstellte Datei „sajat_szabaly.te“ und lassen Sie nur das zu, was tatsächlich erforderlich ist.
Muss SELinux deaktiviert werden?
Wir raten davon ab. Sollte eine Anwendung dennoch nicht damit funktionieren, können Sie anstelle einer vollständigen Deaktivierung nur den betreffenden Dienst in den toleranten Modus versetzen, beispielsweise den Webserver:
sudo semanage permissive -a httpd_t
Sollten Sie SELinux dennoch deaktivieren müssen, bewirkt die Einstellung „SELINUX=disabled“ in der Datei „/etc/selinux/config“ ab AlmaLinux 9 keine vollständige Deaktivierung mehr; geben Sie stattdessen den entsprechenden Wert als Kernel-Parameter an und starten Sie den Server anschließend neu:
sudo grubby --update-kernel ALL --args selinux=0
Wenn Sie den Server später wieder einschalten, muss das gesamte Dateisystem neu gekennzeichnet werden (Befehl „sudo touch /.autorelabel“, gefolgt von einem Neustart), was einige Zeit in Anspruch nehmen kann.
