Utiliser NGINX et NGINX Plus avec SELinux

NGINX | 17 août 2018

Note de la rédaction – L’article de blog intitulé « NGINX : modifications de SELinux lors de la mise à niveau vers RHEL 6.6 / CentOS 6.6 » redirige vers cette page. Le présent article fournit des informations actualisées et plus générales.

Les paramètres par défaut de Security-Enhanced Linux (SELinux) sur les versions modernes de Red Hat Enterprise Linux (RHEL) et les distributions apparentées peuvent être très stricts, privilégiant la sécurité au détriment de la commodité. Bien que les paramètres par défaut ne limitent pas le fonctionnement de NGINX Open Source et de NGINX Plus dans leurs configurations par défaut, d’autres fonctionnalités que vous pourriez configurer peuvent être bloquées si vous ne les autorisez pas explicitement dans SELinux. Cet article décrit les problèmes susceptibles de se produire et les méthodes recommandées pour les résoudre.

[Note de la rédaction – Cet article s’applique à la fois à NGINX Open Source et à NGINX Plus. Pour faciliter la lecture, le terme « NGINX » est utilisé dans l’ensemble de l’article.

CentOS est une distribution apparentée, initialement dérivée de RHEL, qui est prise en charge par NGINX et NGINX Plus. En outre, NGINX Plus prend en charge les distributions apparentées Amazon Linux et Oracle Linux. Leurs paramètres SELinux par défaut peuvent différer de ceux de CentOS et RHEL ; consultez la documentation du fournisseur.]

Présentation de SELinux

SELinux est activé par défaut sur les serveurs RHEL et CentOS modernes. Chaque objet du système d’exploitation (processus, descripteur de fichier, fichier, etc.) est associé à un contexte SELinux qui définit les autorisations et les opérations que l’objet peut effectuer. Dans RHEL 6.6/CentOS 6.6 et les versions ultérieures, NGINX est associé au contexte « httpd_t » :

# 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

Le contexte « httpd_t » permet à NGINX d’écouter sur les ports couramment utilisés par les serveurs web, d’accéder aux fichiers de configuration situés dans /etc/nginx et au contenu de l’emplacement racine standard des documents (/usr/share/nginx). Il n’autorise pas de nombreuses autres opérations, telles que la transmission par proxy vers des serveurs en amont ou la communication avec d’autres processus par l’intermédiaire de sockets.

Désactivation temporaire de SELinux pour NGINX

Pour désactiver temporairement les restrictions SELinux pour le contexte httpd_t afin que NGINX puisse effectuer les mêmes opérations que sur les systèmes d’exploitation sans SELinux, affectez le contexte httpd_t au domaine permissive. Consultez la section suivante pour plus de détails.

# semanage permissive -a httpd_t

Modification des modes SELinux

SELinux peut fonctionner en mode « enforcing », « permissive » ou « disabled » (également appelés « domaines »). Avant d’apporter une modification à la configuration de NGINX susceptible d’enfreindre les autorisations strictes par défaut, vous pouvez faire passer SELinux du mode « enforcing » au mode « permissive », dans votre environnement de test (si disponible) ou de production. En mode « permissive », SELinux autorise toutes les opérations, mais consigne celles qui auraient enfreint la politique de sécurité en mode « enforcing ».

Pour ajouter httpd_t à la liste des domaines permissifs (« permissive »), exécutez la commande suivante :

# semanage permissive -a httpd_t

Pour supprimer httpd_t de la liste des domaines permissifs :

# semanage permissive -d httpd_t

Pour définir globalement le mode sur « permissive », exécutez :

# setenforce 0

Pour définir globalement le mode sur « enforcing », exécutez :

# setenforce 1

Résolution des exceptions de sécurité SELinux

En mode « permissive », les exceptions de sécurité sont consignées dans le journal d’audit Linux par défaut, /var/log/audit/audit.log. Si vous rencontrez un problème qui se produit uniquement lorsque NGINX fonctionne en mode « enforcing », examinez les exceptions consignées en mode « permissive » et mettez à jour la politique de sécurité afin de les autoriser.

Problème 1 : la connexion au proxy est interdite

Par défaut, la configuration SELinux n’autorise pas NGINX à se connecter à des serveurs HTTP, FastCGI ou autres serveurs distants, comme l’indique un message du journal d’audit tel que le suivant :

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)

La commande « audit2why » interprète le code du message (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

La sortie de audit2why indique que vous pouvez autoriser NGINX à établir des connexions proxy en activant l’une des options booléennes httpd_can_network_relay et httpd_can_network_connect, ou les deux. Vous pouvez les activer temporairement ou définitivement ; dans ce dernier cas, ajoutez l’option ‑P comme indiqué dans la sortie.

Comprendre les options booléennes

La commande « sesearch » fournit davantage d’informations sur les options booléennes et est disponible si vous installez le paquet setools (yum install setools). Nous présentons ici la sortie correspondant aux options httpd_can_network_relay et httpd_can_network_connect.

L’option booléenne « httpd_can_network_relay »

Voici le résultat de la commande « sesearch » concernant l’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 ;

Cette sortie indique que « httpd_can_network_relay » permet aux processus associés au contexte « httpd_t » (tels que NGINX) de se connecter à des ports de différents types, notamment ceux du type « http_port_t » :

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

Pour ajouter d’autres ports (ici, « 8082 ») à l’ensemble des ports autorisés pour http_port_t, exécutez :

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

Si la sortie de cette commande indique qu’un port est déjà défini, comme dans l’exemple suivant, cela signifie que le port est inclus dans un autre ensemble. Ne le réaffectez pas à http_port_t, car cela pourrait nuire à d’autres services.

# 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

L’option booléenne « httpd_can_network_connect »

Voici le résultat de la commande sesearch concernant l’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 ;

Cette sortie indique que httpd_can_network_connect autorise les processus associés au contexte httpd_t (comme NGINX) à se connecter à tous les types de sockets TCP possédant l’attribut port_type. Pour les répertorier, exécutez :

# seinfo -aport_type -x

Problème 2 : l’accès au fichier est interdit

Par défaut, la configuration de SELinux n’autorise pas NGINX à accéder aux fichiers situés en dehors des emplacements autorisés connus, comme l’indique un message du journal d’audit tel que le suivant :

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

La commande « audit2why » interprète le code du message (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.

Lorsque l’accès au fichier est interdit, deux options s’offrent à vous.

Option 1 : modifier l’étiquette du fichier

Modifiez l’étiquette du fichier afin que NGINX (en tant que processus associé au contexte httpd_t puisse accéder au fichier :

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

Par défaut, cette modification est supprimée lorsque le système de fichiers est réétiqueté. Pour rendre la modification permanente, exécutez :

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

Pour modifier les étiquettes de groupes de fichiers, exécutez :

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

Option 2 : étendre les autorisations du domaine « httpd_t »

Étendez la politique de httpd_t afin d’autoriser l’accès à des emplacements de fichiers supplémentaires :

# 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;

Pour générer une politique compilée, ajoutez l’option « -M » :

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

Pour charger la politique, exécutez « semodule -i », puis vérifiez que l’opération a réussi avec « semodule -l » :

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

Cette modification persiste après les redémarrages.

Problème 3 : NGINX ne peut pas se lier à des ports supplémentaires

Par défaut, la configuration SELinux n’autorise pas NGINX à écouter (bind()) sur des ports TCP ou UDP autres que ceux par défaut figurant dans la liste d’autorisation du type http_port_t :

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

Si vous essayez de configurer NGINX pour qu’il écoute sur un port ne figurant pas dans la liste des ports autorisés (avec la directive listen dans le contexte http, stream ou mail de la configuration NGINX), une erreur se produit lorsque vous vérifiez la configuration NGINX (nginx -t) ou que vous la rechargez, comme l’indique cette entrée du journal NGINX :

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

Vous pouvez utiliser « semanage » pour ajouter le port souhaité (ici, 8001) au type « http_port_t » :

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

Rechargez NGINX avec la nouvelle configuration.

# nginx -s reload

Problème 4 : « Trop de fichiers sont ouverts »

Lorsque la limite du nombre de fichiers ouverts (RLIMIT_NOFILE) est dépassée, le message suivant apparaît dans le journal des erreurs :

Too many files are open

Lorsque le processus worker NGINX génère l’erreur

Dans la plupart des cas, le processus de travail NGINX signale cette erreur, mais vous ne pouvez pas utiliser la directive NGINX « worker_rlimit_nofile » pour augmenter la limite, car SELinux n’autorise pas l’appel système « setrlimit() », comme l’indiquent les messages suivants dans les journaux d’erreurs et d’audit.

  • Dans /var/log/nginx/error.log pour CentOS/RHEL 7.4+ :
YYYY/MM/DD hh:mm:ss [alert] 12066#0: setrlimit(RLIMIT_NOFILE, 2342) failed (13: Permission denied)
  • Dans « /var/log/nginx/error.log » pour CentOS/RHEL 8.0 et versions ultérieures :
YYYY/MM/DD hh:mm:ss [alert] 3327#0: setrlimit(RLIMIT_NOFILE, 65535) failed (1: Operation not permitted)
  • Dans « /var/log/audit/audit.log » pour CentOS/RHEL 7.4+ et dans « /var/log/messages » pour 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

Pour augmenter la limite, exécutez plutôt cette commande en tant qu’utilisateur root :

$ setsebool -P httpd_setrlimit 1

Lorsque le processus maître NGINX génère l’erreur

Si le processus maître NGINX signale l’erreur, vous devez mettre à jour le fichier systemd unit de NGINX. Cela définit la limite de descripteurs de fichiers pour les processus maître et workers.

  1. Créez un répertoire pour la configuration de « nginx.service » :
$ mkdir /etc/systemd/system/nginx.service.d
  1. Ajoutez les lignes suivantes à « /etc/systemd/system/nginx.service.d/nofile_limit.conf » :
[Service]LimitNOFILE=65535
  1. Rechargez la configuration du démon systemd et redémarrez NGINX :
$ systemctl daemon-reload$ systemctl restart nginx.service

Ressources supplémentaires

SELinux est un mécanisme complexe et puissant de gestion des autorisations du système d’exploitation. Des informations complémentaires sont disponibles dans les documents suivants.


Partager
Mots-clés : F5 NGINX, 2018, Tech

À propos de l’auteur

Owen Garrett
Owen GarrettDirecteur senior de la gestion des produits

Autres articles de Owen Garrett

Articles de blog associés

Tendances actuelles des technologies cloud natives, de l’ingénierie de plateforme et de l’IA
NGINX | 13/10/2025

Tendances actuelles des technologies cloud natives, de l’ingénierie de plateforme et de l’IA

Découvrez les principaux enseignements tirés des réponses à l’enquête annuelle F5 NGINX sur les dernières tendances en matière de technologies cloud natives, de sécurité, d’ingénierie de plateforme et d’IA.

Quels contrôleurs Ingress NGINX sont affectés par les vulnérabilités CVE-2022-4886, CVE-2023-5043 et CVE-2023-5044 ?
NGINX | 03/11/2023

Quels contrôleurs Ingress NGINX sont affectés par les vulnérabilités CVE-2022-4886, CVE-2023-5043 et CVE-2023-5044 ?

Lorsque de nouvelles CVE sont signalées, il est facile de ne plus savoir si elles concernent un outil de contrôleur Ingress NGINX particulier, car il existe plusieurs projets. Cet article présente les CVE et explique comment distinguer les différents projets de contrôleurs Ingress afin de dissiper toute confusion.

Votre API est-elle en temps réel ? Testez sa latence avec l’outil rtapi de NGINX
NGINX | 11/03/2020

Votre API est-elle en temps réel ? Testez sa latence avec l’outil rtapi de NGINX

Votre API répond-elle aux requêtes en moins de 30 ms ? Si ce n’est pas le cas, il ne s’agit pas d’une API en temps réel offrant la faible latence exigée par la grande majorité des organisations. Mesurez la latence de votre API avec l’outil rtapi de NGINX et découvrez comment NGINX peut l’aider à offrir une réactivité en temps réel.

Un testeur d’expressions régulières pour NGINX et NGINX Plus
NGINX | 11/06/2019

Un testeur d’expressions régulières pour NGINX et NGINX Plus

Le testeur d’expressions régulières (regex) pour NGINX et NGINX Plus vous évite de tâtonner en vous indiquant si une expression régulière utilisée dans un bloc location ou map correspond aux valeurs comme prévu. Il génère la configuration appropriée et affiche les valeurs des groupes de capture.

Caches partagés avec les clusters de cache NGINX Plus, partie 1
NGINX | 24/01/2017

Caches partagés avec les clusters de cache NGINX Plus, partie 1

Optimisez la capacité de votre cache web en le répartissant entre plusieurs serveurs de cache web NGINX ou NGINX Plus. Découvrez comment procéder dans cet article.

Introduction aux microservices
NGINX | 19/05/2015

Introduction aux microservices

Les microservices suscitent actuellement beaucoup d’intérêt. Cet article de blog est le premier d’une série de sept consacrée à la conception, au développement et au déploiement de microservices.