NGINX und NGINX Plus mit SELinux verwenden

NGINX | 17. August 2018

Anmerkung der Redaktion – Der Blogbeitrag mit dem Titel „NGINX: SELinux-Änderungen beim Upgrade auf RHEL 6.6 / CentOS 6.6“ verweist auf diese Seite. Dieser Artikel enthält aktualisierte und allgemeiner gefasste Informationen.

Die Standardeinstellungen für Security-Enhanced Linux (SELinux) unter modernen Versionen von Red Hat Enterprise Linux (RHEL) und verwandten Distributionen können sehr streng sein und räumen der Sicherheit Vorrang vor der Benutzerfreundlichkeit ein. Obwohl die Standardeinstellungen die Funktionsweise von NGINX Open Source und NGINX Plus in ihren Standardkonfigurationen nicht einschränken, können andere von Ihnen konfigurierte Funktionen blockiert werden, sofern Sie diese nicht ausdrücklich in SELinux zulassen. Dieser Artikel beschreibt mögliche Probleme und empfohlene Lösungswege.

[Redaktion – Dieser Artikel gilt sowohl für NGINX Open Source als auch für NGINX Plus. Zur besseren Lesbarkeit wird durchgehend der Begriff „NGINX“ verwendet.

CentOS ist eine verwandte Distribution, die ursprünglich von RHEL abgeleitet wurde und von NGINX und NGINX Plus unterstützt wird. Darüber hinaus unterstützt NGINX Plus die verwandten Distributionen Amazon Linux und Oracle Linux. Deren standardmäßige SELinux-Einstellungen können von denen unter CentOS und RHEL abweichen. Weitere Informationen finden Sie in der Dokumentation des jeweiligen Anbieters.]

Überblick über SELinux

SELinux ist auf modernen RHEL- und CentOS-Servern standardmäßig aktiviert. Jedes Betriebssystemobjekt (Prozess, Dateideskriptor, Datei usw.) ist mit einem SELinux-Kontext gekennzeichnet, der die Berechtigungen und Vorgänge festlegt, die das Objekt ausführen kann. Ab RHEL 6.6/CentOS 6.6 ist NGINX mit dem Kontext „httpd_t“ gekennzeichnet:

# ps auZ | grep nginxunconfined_u:system_r:httpd_t:s0 3234 ? Ss 0:00 nginx: master process /usr/sbin/nginx \
                                                -c /etc/nginx/nginx.conf
unconfined_u:system_r:httpd_t:s0 3236 ? Ss 0:00 nginx: worker process

Der Kontext httpd_t erlaubt NGINX, an gängigen Webserver-Ports zu lauschen, auf Konfigurationsdateien in /etc/nginx und auf Inhalte im standardmäßigen Dokumentenstammverzeichnis (/usr/share/nginx) zuzugreifen. Viele andere Vorgänge sind jedoch nicht zulässig, beispielsweise die Weiterleitung an Upstream-Ziele oder die Kommunikation mit anderen Prozessen über Sockets.

SELinux für NGINX vorübergehend deaktivieren

Um die SELinux-Einschränkungen für den Kontext httpd_t vorübergehend zu deaktivieren, damit NGINX dieselben Vorgänge wie auf Betriebssystemen ohne SELinux ausführen kann, weisen Sie den Kontext httpd_t der Domäne permissive zu. Weitere Informationen finden Sie im nächsten Abschnitt.

# semanage permissive -a httpd_t

SELinux-Modi ändern

SELinux kann in den Modi Enforcing, Permissive oder Disabled ausgeführt werden (auch als Domänen bezeichnet). Bevor Sie eine Änderung an der NGINX-Konfiguration vornehmen, die möglicherweise gegen die standardmäßigen (strikten) Berechtigungen verstößt, können Sie SELinux in Ihrer Testumgebung (sofern vorhanden) oder Produktionsumgebung vom Modus Enforcing in den Modus Permissive versetzen. Im Modus Permissive lässt SELinux alle Vorgänge zu, protokolliert jedoch Vorgänge, die im Modus Enforcing gegen die Sicherheitsrichtlinie verstoßen hätten.

Um httpd_t zur Liste der permissiven Domänen hinzuzufügen, führen Sie diesen Befehl aus:

# semanage permissive -a httpd_t

Um httpd_t aus der Liste der permissiven Domänen zu entfernen, führen Sie folgenden Befehl aus:

# semanage permissive -d httpd_t

Um den Modus global auf „permissive“ festzulegen, führen Sie Folgendes aus:

# setenforce 0

Um den Modus global auf „enforcing“ festzulegen, führen Sie Folgendes aus:

# setenforce 1

Beheben von SELinux-Sicherheitsausnahmen

Im permissiven Modus werden Sicherheitsausnahmen im standardmäßigen Linux-Audit-Protokoll /var/log/audit/audit.log protokolliert. Wenn ein Problem nur auftritt, wenn NGINX im erzwingenden Modus ausgeführt wird, überprüfen Sie die im permissiven Modus protokollierten Ausnahmen und aktualisieren Sie die Sicherheitsrichtlinie, um sie zuzulassen.

Problem 1: Proxy-Verbindung ist nicht zulässig

Standardmäßig erlaubt die SELinux-Konfiguration NGINX keine Verbindungen zu entfernten HTTP-, FastCGI- oder anderen Servern. Darauf weist eine Audit-Protokollmeldung wie die folgende hin:

type=AVC msg=audit(1415714880.156:29): avc:  denied  { name_connect } for  pid=1349 \
  comm="nginx" dest=8080 scontext=unconfined_u:system_r:httpd_t:s0 \
  tcontext=system_u:object_r:http_cache_port_t:s0 tclass=tcp_socket
type=SYSCALL msg=audit(1415714880.156:29): arch=c000003e syscall=42 success=no \
  exit=-115 a0=b \a1=16125f8 a2=10 a3=7fffc2bab440 items=0 ppid=1347 pid=1349 \
  auid=1000 uid=497 gid=496 euid=497 suid=497 fsuid=497 egid=496 sgid=496 fsgid=496 \
  tty=(none) ses=1 comm="nginx" exe="/usr/sbin/nginx" \
  subj=unconfined_u:system_r:httpd_t:s0 key=(null)

Der Befehl „audit2why“ interpretiert den Meldungscode (1415714880.156:29):

# grep 1415714880.156:29 /var/log/audit/audit.log | audit2whytype=AVC msg=audit(1415714880.156:29): avc:  denied  { name_connect } for  pid=1349 \
  comm="nginx" dest=8080 scontext=unconfined_u:system_r:httpd_t:s0 \
  tcontext=system_u:object_r:http_cache_port_t:s0 tclass=tcp_socket
 
        Was caused by:
        One of the following booleans was set incorrectly.
        Description:
        Allow httpd to act as a relay
 
        Allow access by executing:
        # setsebool -P httpd_can_network_relay 1
        Description:
        Allow HTTPD scripts and modules to connect to the network using TCP.
 
        Allow access by executing:
        # setsebool -P httpd_can_network_connect 1

Die Ausgabe von audit2why zeigt, dass Sie NGINX Proxy-Verbindungen erlauben können, indem Sie eine oder beide der booleschen Optionen httpd_can_network_relay und httpd_can_network_connect aktivieren. Sie können diese entweder vorübergehend oder dauerhaft aktivieren. Für Letzteres fügen Sie wie in der Ausgabe gezeigt das Flag ‑P hinzu.

Boolesche Optionen verstehen

Der Befehl „sesearch“ liefert weitere Informationen zu den booleschen Optionen und ist verfügbar, wenn Sie das Paket „setools“ installieren (yum install setools). Hier zeigen wir die Ausgabe für die Optionen „httpd_can_network_relay“ und „httpd_can_network_connect“.

Die boolesche Option „httpd_can_network_relay“

Hier ist die Ausgabe des Befehls „sesearch“ zur Option „httpd_can_network_relay“:

# sesearch -A -s httpd_t -b httpd_can_network_relayFound 10 semantic av rules:
   allow httpd_t gopher_port_t : tcp_socket name_connect ;
   allow httpd_t http_cache_client_packet_t : packet { send recv } ;
   allow httpd_t ftp_port_t : tcp_socket name_connect ;
   allow httpd_t ftp_client_packet_t : packet { send recv } ;
   allow httpd_t http_client_packet_t : packet { send recv } ;
   allow httpd_t squid_port_t : tcp_socket name_connect ;
   allow httpd_t http_cache_port_t : tcp_socket name_connect ;
   allow httpd_t http_port_t : tcp_socket name_connect ;
   allow httpd_t gopher_client_packet_t : packet { send recv } ;
   allow httpd_t memcache_port_t : tcp_socket name_connect ;

Diese Ausgabe zeigt, dass httpd_can_network_relay Prozessen mit dem Kontext httpd_t (wie etwa NGINX) erlaubt, Verbindungen zu Ports verschiedener Typen herzustellen, darunter auch zum Typ http_port_t:

# semanage port -l | grep http_port_thttp_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000

Um weitere Ports (hier 8082) zur Liste der für http_port_t zulässigen Ports hinzuzufügen, führen Sie folgenden Befehl aus:

# semanage port -a -t http_port_t -p tcp 8082

Wenn die Ausgabe dieses Befehls besagt, dass ein Port bereits definiert ist, wie im folgenden Beispiel, bedeutet dies, dass der Port in einer anderen Gruppe enthalten ist. Weisen Sie ihn nicht erneut http_port_t zu, da dies andere Dienste beeinträchtigen könnte.

# semanage port -a -t http_port_t -p tcp 8080
/usr/sbin/semanage: Port tcp/8080 already defined
# semanage port -l | grep 8080
http_cache_port_t              tcp      3128, 8080, 8118, 8123, 10001-10010

Die boolesche Option „httpd_can_network_connect“

Hier ist die Ausgabe des Befehls „sesearch“ zur Option „httpd_can_network_connect“:

# sesearch -A -s httpd_t -b httpd_can_network_connectFound 1 semantic av rules:
   allow httpd_t port_type : tcp_socket name_connect ;

Diese Ausgabe zeigt, dass „httpd_can_network_connect“ Prozessen mit dem Kontext „httpd_t“ (wie etwa NGINX) erlaubt, eine Verbindung zu allen TCP-Socket-Typen herzustellen, die das Attribut „port_type“ aufweisen. Führen Sie folgenden Befehl aus, um sie aufzulisten:

# seinfo -aport_type -x

Problem 2: Der Dateizugriff ist nicht zulässig

Standardmäßig erlaubt die SELinux-Konfiguration NGINX nicht, auf Dateien außerhalb bekannter autorisierter Speicherorte zuzugreifen, worauf eine Audit-Protokollmeldung wie die folgende hinweist:

type=AVC msg=audit(1415715270.766:31): avc:  denied  { getattr } for  pid=1380 \
  comm="nginx" path="/www/t.txt" dev=vda1 ino=1084 \
  scontext=unconfined_u:system_r:httpd_t:s0 \
  tcontext=unconfined_u:object_r:default_t:s0 tclass=file

Der Befehl „audit2why“ interpretiert den Meldungscode (1415715270.766:31):

# grep 1415715270.766:31 /var/log/audit/audit.log | audit2whytype=AVC msg=audit(1415715270.766:31): avc:  denied  { getattr } for  pid=1380 \
  comm="nginx" path="/www/t.txt" dev=vda1 ino=1084 \
  scontext=unconfined_u:system_r:httpd_t:s0 \
  tcontext=unconfined_u:object_r:default_t:s0 tclass=file
 
    Was caused by:
        Missing type enforcement (TE) allow rule.
 
        You can use audit2allow to generate a loadable module to allow this access.

Wenn der Dateizugriff verweigert wird, haben Sie zwei Möglichkeiten.

Option 1: Dateikennzeichnung ändern

Ändern Sie den Dateikontext so, dass NGINX (als Prozess mit dem Kontext httpd_t gekennzeichnet) auf die Datei zugreifen kann:

# chcon -v --type=httpd_sys_content_t /www/t.txt

Standardmäßig wird diese Änderung gelöscht, wenn das Dateisystem neu gekennzeichnet wird. Um die Änderung dauerhaft zu übernehmen, führen Sie Folgendes aus:

# semanage fcontext -a -t httpd_sys_content_t /www/t.txt
# restorecon -v /www/t.txt

Um Datei-Labels für Gruppen von Dateien zu ändern, führen Sie Folgendes aus:

# semanage fcontext -a -t httpd_sys_content_t '/www(/.*)?'# restorecon -Rv /www

Option 2: Erweitern der Berechtigungen der Domain httpd_t Domain Permissions

Erweitern Sie die Richtlinie für „httpd_t“, um den Zugriff auf zusätzliche Dateispeicherorte zu ermöglichen:

# grep nginx /var/log/audit/audit.log | audit2allow -m nginx > nginx.te# cat nginx.te
 
module nginx 1.0;
 
require {
        type httpd_t;
        type default_t;
        type http_cache_port_t;
        class tcp_socket name_connect;
        class file { read getattr open };
}
 
#============= httpd_t ==============
allow httpd_t default_t:file { read getattr open };
 
#!!!! This avc can be allowed using one of these booleans:
#     httpd_can_network_relay, httpd_can_network_connect
allow httpd_t http_cache_port_t:tcp_socket name_connect;

Um eine kompilierte Richtlinie zu generieren, verwenden Sie die Option „-M“:

# grep nginx /var/log/audit/audit.log | audit2allow -M nginx

Um die Richtlinie zu laden, führen Sie semodule -i aus und überprüfen Sie anschließend mit semodule -l, ob der Vorgang erfolgreich war:

# semodule -i nginx.pp
# semodule -l | grep nginx
nginx 1.0

Diese Änderung bleibt auch nach einem Neustart bestehen.

Problem 3: NGINX kann keine Bindung an zusätzliche Ports herstellen

Standardmäßig erlaubt die SELinux-Konfiguration NGINX nicht, andere als die standardmäßig zugelassenen TCP- oder UDP-Ports zu verwenden (bind()). Diese Standardports sind im Typ http_port_t aufgeführt:

# semanage port -l | grep http_port_thttp_port_t                    tcp      80, 443, 488, 8008, 8009, 8443

Wenn Sie versuchen, NGINX so zu konfigurieren, dass es einen Port überwacht, der nicht auf der Zulassungsliste steht (mit der listen-Direktive im http-, stream- oder mail-Kontext der NGINX-Konfiguration), erhalten Sie beim Überprüfen (nginx -t) oder erneuten Laden der NGINX-Konfiguration einen Fehler, wie dieser NGINX-Protokolleintrag zeigt:

YYYY/MM/DD hh:mm:ss [emerg] 46123#0: bind() to 0.0.0.0:8001 failed (13: Permission denied)

Mit semanage können Sie den gewünschten Port (hier 8001) dem Typ http_port_t hinzufügen:

# semanage port -a -t http_port_t -p tcp 8001

Laden Sie NGINX mit der neuen Konfiguration neu.

# nginx -s reload

Problem 4: „Zu viele Dateien sind geöffnet“-Fehler

Wenn die Höchstzahl der geöffneten Dateien (RLIMIT_NOFILE) überschritten wird, erscheint die folgende Meldung im Fehlerprotokoll:

Too many files are open

Wenn der NGINX-Worker-Prozess den Fehler erzeugt

In den meisten Fällen meldet der NGINX-Worker-Prozess diesen Fehler. Sie können jedoch die NGINX-Direktive „worker_rlimit_nofile“ nicht verwenden, um den Grenzwert zu erhöhen, da SELinux den Systemaufruf „setrlimit()“ nicht zulässt, wie die folgenden Meldungen in den Fehler- und Audit-Protokollen zeigen.

  • In /var/log/nginx/error.log für CentOS/RHEL 7.4+:
YYYY/MM/DD hh:mm:ss [alert] 12066#0: setrlimit(RLIMIT_NOFILE, 2342) failed (13: Permission denied)
  • In /var/log/nginx/error.log für CentOS/RHEL 8.0+:
YYYY/MM/DD hh:mm:ss [alert] 3327#0: setrlimit(RLIMIT_NOFILE, 65535) failed (1: Operation not permitted)
  • In /var/log/audit/audit.log für CentOS/RHEL 7.4+ und /var/log/messages für CentOS/RHEL 8.0+:
type=AVC msg=audit(1437731200.211:366): avc:  denied  { setrlimit } for pid=12066 \  comm="nginx" scontext=system_u:system_r:httpd_t:s0 \
  tcontext=system_u:system_r:httpd_t:s0 tclass=process

Um das Limit zu erhöhen, führen Sie stattdessen diesen Befehl als root-Benutzer aus:

$ setsebool -P httpd_setrlimit 1

Wenn der NGINX-Masterprozess den Fehler verursacht

Wenn der NGINX-Masterprozess den Fehler meldet, müssen Sie die systemd-unit-Datei für NGINX aktualisieren. Dadurch wird die maximale Anzahl der Dateideskriptoren sowohl für den Master- als auch für die Worker-Prozesse festgelegt.

  1. Erstellen Sie ein Verzeichnis für die nginx.service-Konfiguration:
$ mkdir /etc/systemd/system/nginx.service.d
  1. Fügen Sie die folgenden Zeilen in „/etc/systemd/system/nginx.service.d/nofile_limit.conf“ ein:
[Service]LimitNOFILE=65535
  1. Laden Sie die systemd-Daemon-Konfiguration neu und starten Sie NGINX neu:
$ systemctl daemon-reload$ systemctl restart nginx.service

Weitere Ressourcen

SELinux ist eine komplexe und leistungsfähige Funktion zur Verwaltung von Berechtigungen im Betriebssystem. Weitere Informationen finden Sie in den folgenden Dokumenten.


Teilen
Schlagwörter: F5 NGINX, 2018, Tech

Über den Autor

Owen Garrett
Owen GarrettSenior Director, Produktmanagement

Weitere Blogbeiträge von Owen Garrett

Ähnliche Blogbeiträge

Die Zukunft von NGINX: Zurück zu unseren Open-Source-Wurzeln
NGINX | 23.08.2022

Die Zukunft von NGINX: Zurück zu unseren Open-Source-Wurzeln

Beim NGINX Sprint 2022 besinnen wir uns auf unsere Open-Source-Wurzeln. Erfahren Sie mehr über die Initiativen, die wir im kommenden Jahr verfolgen, und teilen Sie uns mit, was Sie sich wünschen.

Ein Leitfaden zur Auswahl eines Ingress-Controllers, Teil 1: Ermitteln Sie Ihre Anforderungen
NGINX | 08.09.2021

Ein Leitfaden zur Auswahl eines Ingress-Controllers, Teil 1: Ermitteln Sie Ihre Anforderungen

Ein Ingress-Controller kann eines der leistungsstärksten Tools in Ihrem Kubernetes-Stack sein. Erfahren Sie, wie Sie Ihre Ingress-Anforderungen ermitteln, um die beste Option auszuwählen.

Bereitstellung des NGINX Ingress Controllers auf Amazon EKS: So haben wir getestet
NGINX | 16.08.2021

Bereitstellung des NGINX Ingress Controllers auf Amazon EKS: So haben wir getestet

Wir haben kürzlich den Lösungsleitfaden zum NGINX Ingress Controller um Empfehlungen zur Dimensionierung für Amazon Elastic Kubernetes Service (EKS) ergänzt. In diesem Blogbeitrag erläutern wir, wie wir diese Empfehlungen erarbeitet haben, und stellen Ihnen alle Informationen zur Verfügung, die Sie benötigen, um selbst ähnliche Tests durchzuführen.

Protokollierung des Datenverkehrs zwischen NGINX und Upstream-Servern bei CDN77
NGINX | 12.12.2018

Protokollierung des Datenverkehrs zwischen NGINX und Upstream-Servern bei CDN77

Bei der Fehlersuche bei Datenverkehrsproblemen zwischen NGINX und Upstream-Servern konnte CDN77 die benötigten Daten nur aus dem Fehlerprotokoll mit aktivierter Debug-Ausgabe beziehen, was die Leistung beeinträchtigt und riesige Dateien erzeugt. Daher entwickelte das Team ein neues benutzerdefiniertes Modul, das ausschließlich die benötigten Daten protokolliert.

Ankündigung von NGINX Plus R16
NGINX | 05.09.2018

Ankündigung von NGINX Plus R16

NGINX Plus R16 ist eine einheitliche, elastische Ingress- und Egress-Schicht für Anwendungen, die die Funktionen eines Load Balancers, API-Gateways und einer WAF vereint und neue Features wie clusterfähige Ratenbegrenzung, Schlüssel-Wert-Speicher, „Random with Two Choices“, verbessertes UDP-Load-Balancing und vieles mehr bietet.

5 Gründe für den Umstieg auf softwarebasiertes Load Balancing
NGINX | 13.10.2016

5 Gründe für den Umstieg auf softwarebasiertes Load Balancing

Entdecken Sie fünf Gründe für den Wechsel zu einem softwarebasierten Load Balancer wie NGINX Plus, darunter Kosteneinsparungen, die Einführung von DevOps und eine einheitliche Lösung für alle Umgebungen.