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.
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
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.
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.
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
.
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
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
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.
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
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.
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
Trop de fichiers sont ouverts
ErreurLorsque 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
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
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.
Créez un répertoire pour la configuration de nginx.service
:
$ mkdir /etc/systemd/system/nginx.service.d
Ajoutez les lignes suivantes à /etc/systemd/system/nginx.service.d/nofile_limit.conf :
[Service]LimitNOFILE=65535
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."