BLOG | NGINX

Utilisation de NGINX et NGINX Plus avec SELinux

Vignette d'Owen Garrett
Owen Garrett
Publié le 17 août 2018

Rédacteur en chef – L’article de blog intitulé « NGINX : « Modifications de SELinux lors de la mise à niveau vers RHEL 6.6 / CentOS 6.6 » redirige ici. Cet article fournit des informations mises à jour et généralisées.

Les paramètres par défaut de Security-Enhanced Linux (SELinux) sur les distributions modernes Red Hat Enterprise Linux (RHEL) et associées peuvent être très stricts, privilégiant la sécurité plutôt que la commodité. Bien que les paramètres par défaut ne limitent pas le fonctionnement de NGINX Open Source et NGINX Plus dans leurs configurations par défaut, d'autres fonctionnalités que vous pourriez configurer peuvent être bloquées à moins que vous ne les autorisiez explicitement dans SELinux. Cet article décrit les problèmes possibles et les méthodes recommandées pour les résoudre.

[Éditeur – Cet article s’applique à la fois à NGINX Open Source et à NGINX Plus. Pour faciliter la lecture, le terme « NGINX » est utilisé tout au long du document.

CentOS est une distribution apparentée dérivée à l'origine de RHEL et prise en charge par NGINX et NGINX Plus. De plus, NGINX Plus prend en charge les distributions Amazon Linux et Oracle Linux associées. 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 étiqueté avec 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 versions ultérieures, NGINX est étiqueté avec le 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 de serveur Web courants, d'accéder aux fichiers de configuration dans /etc/nginx et d'accéder au contenu dans l'emplacement docroot standard ( /usr/share/nginx ). Il ne permet pas de nombreuses autres opérations, telles que la proxy vers des emplacements en amont ou la communication avec d'autres processus via des 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 toutes les mêmes opérations que dans les systèmes d’exploitation non SELinux, attribuez le contexte httpd_t au domaine permissif . Voir la section suivante pour plus de détails.

# semanage permissive -a httpd_t

Modification des modes SELinux

SELinux peut être exécuté en modes contraignant , permissif ou désactivé (également appelés domaines ). Avant d'effectuer une modification de configuration NGINX susceptible de violer les autorisations par défaut (strictes), vous pouvez modifier SELinux du mode contraignant au mode permissif , dans votre environnement de test (si disponible) ou dans votre environnement de production. En mode permissif , SELinux autorise toutes les opérations, mais enregistre les opérations qui auraient violé la politique de sécurité en mode d'application .

Pour ajouter httpd_t à la liste des domaines permissifs , exécutez cette commande :

# semanage permissive -a httpd_t

Pour supprimer httpd_t de la liste des domaines permissifs , exécutez :

# semanage permissive -d httpd_t

Pour définir le mode globalement sur permissif , exécutez :

# setenforce 0

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

# setenforce 1

Résolution des exceptions de sécurité SELinux

En mode permissif , les exceptions de sécurité sont enregistré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 s'exécute en mode d'application , examinez les exceptions enregistrées en mode permissif et mettez à jour la politique de sécurité pour les autoriser.

Numéro 1 : La connexion proxy est interdite

Par défaut, la configuration SELinux ne permet pas à NGINX de se connecter à des serveurs HTTP, FastCGI ou autres distants, comme indiqué par un message de journal d'audit comme 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 ou les deux options booléennes httpd_can_network_relay et httpd_can_network_connect . Vous pouvez les activer temporairement ou définitivement, dans ce dernier cas en ajoutant l'indicateur -P comme indiqué dans la sortie.

Comprendre les options booléennes

La commande sesearch fournit plus d'informations sur les options booléennes et est disponible si vous installez le package setools ( yum install setools ). Nous montrons ici la sortie pour les 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 étiquetés avec le contexte httpd_t (tel que NGINX) de se connecter à des ports de différents types, y compris le type http_port_t :

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

Pour ajouter plus de 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 d'autres services pourraient être affectés négativement.

# 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 permet aux processus étiquetés avec le contexte httpd_t (tel que NGINX) de se connecter à tous les types de sockets TCP qui ont l'attribut port_type . Pour les lister, exécutez :

# seinfo -aport_type -x

Numéro 2 : L'accès au fichier est interdit

Par défaut, la configuration SELinux n’autorise pas NGINX à accéder aux fichiers en dehors des emplacements autorisés connus, comme indiqué par un message de 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 aux fichiers est interdit, vous avez deux options.

Option 1 : Modifier l'étiquette du fichier

Modifiez l'étiquette du fichier afin que NGINX (en tant que processus étiqueté avec le 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 le changement permanent, exécutez :

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

Pour modifier les étiquettes de fichiers pour des 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 pour httpd_t pour 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, incluez l'option -M :

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

Pour charger la politique, exécutez semodule -i , puis vérifiez le succès avec semodule -l :

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

Ce changement persiste après les redémarrages.

Numéro 3 : NGINX ne peut pas se lier à des ports supplémentaires

Par défaut, la configuration SELinux n'autorise pas NGINX à écouter ( bind() ) les ports TCP ou UDP autres que ceux par défaut qui sont sur liste blanche dans le 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 écouter sur un port non autorisé (avec la directive listen dans le contexte http , stream ou mail dans la configuration NGINX), vous obtenez une erreur lorsque vous vérifiez ( nginx -t ) ou rechargez la configuration NGINX, comme indiqué par cette entrée de 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

Numéro 4 : Trop de fichiers sont ouverts Erreur

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 de travail 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 indiqué dans les messages suivants dans les journaux d'erreur 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+ :

    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 /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 d'unité systemd pour NGINX. Cela définit la limite du descripteur de fichier pour les processus maître et de travail.

  1. Créez un répertoire pour la configuration de nginx.service :

    $ mkdir /etc/systemd/system/nginx.service.d
    
  2. Ajoutez les lignes suivantes à /etc/systemd/system/nginx.service.d/nofile_limit.conf :

    [Service]LimitNOFILE=65535
    
  3. Rechargez la configuration du démon systemd et redémarrez NGINX :

    $ systemctl daemon-reload$ systemctl restart nginx.service
    

Ressources complémentaires

SELinux est un outil complexe et puissant permettant de gérer les autorisations du système d'exploitation. Des informations complémentaires sont disponibles dans les documents suivants.


« Cet article de blog peut faire référence à des produits qui ne sont plus disponibles et/ou qui ne sont plus pris en charge. Pour obtenir les informations les plus récentes sur les produits et solutions F5 NGINX disponibles, explorez notre famille de produits NGINX . NGINX fait désormais partie de F5. Tous les liens NGINX.com précédents redirigeront vers un contenu NGINX similaire sur F5.com."