Editor – La publicación del blog titulada “NGINX: “Cambios de SELinux al actualizar a RHEL 6.6 / CentOS 6.6” redirige aquí. Este artículo proporciona información actualizada y generalizada.
La configuración predeterminada para Security-Enhanced Linux (SELinux) en Red Hat Enterprise Linux (RHEL) moderno y distribuciones relacionadas puede ser muy estricta y estar más a favor de la seguridad que de la conveniencia. Aunque la configuración predeterminada no limita el funcionamiento de NGINX Open Source y NGINX Plus en sus configuraciones predeterminadas, otras funciones que pueda configurar pueden bloquearse a menos que las permita explícitamente en SELinux. Este artículo describe los posibles problemas y las formas recomendadas de resolverlos.
[Editor: Este artículo se aplica tanto a NGINX Open Source como a NGINX Plus. Para facilitar la lectura, se utiliza el término “NGINX” en todo el documento.
CentOS es una distribución relacionada originalmente derivada de RHEL y es compatible con NGINX y NGINX Plus. Además, NGINX Plus es compatible con las distribuciones Amazon Linux y Oracle Linux relacionadas. Su configuración SELinux predeterminada puede diferir de CentOS y RHEL; consulte la documentación del proveedor.]
Descripción general de SELinux
SELinux está habilitado de forma predeterminada en los servidores RHEL y CentOS modernos. Cada objeto del sistema operativo (proceso, descriptor de archivo, archivo, etc.) está etiquetado con un contexto SELinux que define los permisos y las operaciones que el objeto puede realizar. En RHEL 6.6/CentOS 6.6 y versiones posteriores, NGINX está etiquetado con el contexto httpd_t
:
# ps auZ | grep nginx unconfined_u:system_r: httpd_t :s0 3234 ? Ss 0:00 nginx: proceso maestro /usr/sbin/nginx \ -c /etc/nginx/nginx.conf unconfined_u:system_r: httpd_t :s0 3236 ? Ss 0:00 nginx: proceso de trabajo
El contexto httpd_t
permite a NGINX escuchar en puertos de servidor web comunes, acceder a archivos de configuración en /etc/nginx y acceder al contenido en la ubicación docroot estándar ( /usr/share/nginx ). No permite muchas otras operaciones, como la conexión a ubicaciones ascendentes o la comunicación con otros procesos a través de sockets.
Para deshabilitar temporalmente las restricciones de SELinux para el contexto httpd_t
, de modo que NGINX pueda realizar las mismas operaciones que en sistemas operativos que no sean SELinux, asigne el contexto httpd_t
al dominio permisivo . Consulte la siguiente sección para obtener más detalles.
# semanage permisivo -a httpd_t
SELinux se puede ejecutar en modos de aplicación , permisivo o deshabilitado (también denominados dominios ). Antes de realizar un cambio de configuración de NGINX que pueda infringir los permisos predeterminados (estrictos), puede cambiar SELinux del modo obligatorio al modo permisivo , en su entorno de prueba (si está disponible) o en su entorno de producción. En el modo permisivo , SELinux permite todas las operaciones, pero registra las operaciones que habrían violado la política de seguridad en el modo de aplicación .
Para agregar httpd_t
a la lista de dominios permisivos , ejecute este comando:
# semanage permisivo -a httpd_t
Para eliminar httpd_t
de la lista de dominios permisivos , ejecute:
# semanage permisivo -d httpd_t
Para establecer el modo globalmente en permisivo , ejecute:
# setenforce 0
Para establecer el modo globalmente en enforcing , ejecute:
# setenforce 1
Resolución de excepciones de seguridad de SELinux
En el modo permisivo , las excepciones de seguridad se registran en el registro de auditoría predeterminado de Linux, /var/log/audit/audit.log . Si encuentra un problema que ocurre solo cuando NGINX se ejecuta en modo de aplicación , revise las excepciones registradas en modo permisivo y actualice la política de seguridad para permitirlas.
De forma predeterminada, la configuración de SELinux no permite que NGINX se conecte a servidores HTTP, FastCGI u otros servidores remotos, como lo indica un mensaje de registro de auditoría como el siguiente:
Tipo=AVC msg=audit(1415714880.156:29): avc: conexión denegada {nombre_conexión} para 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
Tipo=SYSCALL msg=audit(1415714880.156:29): arch=c000003e syscall=42 éxito=no \
salida=-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=(ninguno) ses=1 comm="nginx" exe="/usr/sbin/nginx" \
subj=unconfined_u:system_r:httpd_t:s0 clave=(nulo)
El comando audit2why
interpreta el código del mensaje ( 1415714880.156:29
):
# grep 1415714880.156:29 /var/log/audit/audit.log | audit2why tipo=AVC msg=audit(1415714880.156:29): avc: se denegó { name_connect } para 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 Fue causado por:
Uno de los siguientes valores booleanos se configuró incorrectamente.
Descripción:
Permitir que httpd actúe como relé Permitir el acceso ejecutando: # setsebool -P httpd_can_network_relay 1 Descripción:
Permitir que los scripts y módulos HTTPD se conecten a la red mediante TCP.
Permitir el acceso ejecutando: # setsebool -P httpd_can_network_connect 1
La salida de audit2why
indica que puede permitir que NGINX realice conexiones proxy habilitando una o ambas de las opciones booleanas httpd_can_network_relay
y httpd_can_network_connect
. Puede habilitarlos de forma temporal o permanente, esto último agregando el indicador -P
como se muestra en la salida.
El comando sesearch
proporciona más información sobre las opciones booleanas y está disponible si instala el paquete setools ( yum
install
setools
). Aquí mostramos la salida de las opciones httpd_can_network_relay
y httpd_can_network_connect
.
httpd_can_network_relay
Aquí está el resultado del comando sesearch
sobre la opción httpd_can_network_relay
:
# sesearch -A -s httpd_t -b httpd_can_network_relay Se encontraron 10 reglas anti-virus semánticas: permitir httpd_t gopher_port_t : tcp_socket nombre_conexión ; permitir httpd_t http_cache_client_packet_t : paquete { enviar recepción } ; permitir httpd_t ftp_port_t : tcp_socket nombre_conexión ; permitir httpd_t ftp_client_packet_t : paquete { enviar recepción } ; permitir httpd_t http_client_packet_t : paquete { enviar recepción } ; permitir httpd_t squid_port_t : tcp_socket nombre_conexión ; permitir httpd_t http_cache_port_t : tcp_socket nombre_conexión ; permitir httpd_t http_port_t : tcp_socket nombre_conexión ; permitir httpd_t gopher_client_packet_t : paquete { enviar recepción } ; permitir httpd_t memcache_port_t : tcp_socket nombre_conexión ;
Esta salida indica que httpd_can_network_relay
permite que los procesos etiquetados con el contexto httpd_t
(como NGINX) se conecten a puertos de varios tipos, incluido el tipo http_port_t
:
# semanage puerto -l | grep http_port_t http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
Para agregar más puertos (aquí,8082
) al conjunto de puertos permitidos para http_port_t
, ejecute:
# semanage puerto -a -t http_port_t -p tcp 8082
Si la salida de este comando indica que un puerto ya
está definido
, como en el siguiente ejemplo, significa que el puerto está incluido en otro conjunto. No lo reasigne a http_port_t
, porque otros servicios podrían verse afectados negativamente.
# semanage puerto -a -t http_port_t -p tcp 8080 /usr/sbin/semanage: Puerto tcp/8080 ya definido # semanage port -l | grep 8080 http_cache_port_t tcp 3128, 8080, 8118, 8123, 10001-10010
httpd_can_network_connect
Aquí está el resultado del comando sesearch
sobre la opción httpd_can_network_connect
:
# sesearch -A -s httpd_t -b httpd_can_network_connect Se encontraron 1 reglas anti-v semánticas: permitir httpd_t port_type : tcp_socket name_connect ;
Esta salida indica que httpd_can_network_connect
permite que los procesos etiquetados con el contexto httpd_t
(como NGINX) se conecten a todos los tipos de sockets TCP que tengan el atributo port_type
. Para enumerarlos, ejecute:
# seinfo -aport_type -x
De forma predeterminada, la configuración de SELinux no permite que NGINX acceda a archivos fuera de ubicaciones autorizadas conocidas, como lo indica un mensaje de registro de auditoría como el siguiente:
tipo=AVC msg=audit(1415715270.766:31): avc: denegado { getattr } para 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
El comando audit2why
interpreta el código del mensaje ( 1415715270.766:31
):
# grep 1415715270.766:31 /var/log/audit/audit.log | audit2why tipo=AVC msg=audit(1415715270.766:31): avc: denegado { getattr } para 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 Fue causado por:
Falta la regla de permiso de aplicación de tipo (TE).
Puede utilizar audit2allow para generar un módulo cargable para permitir este acceso.
Cuando el acceso a los archivos está prohibido, tienes dos opciones.
Modifique la etiqueta del archivo para que NGINX (como un proceso etiquetado con el contexto httpd_t
) pueda acceder al archivo:
# chcon -v --type=httpd_sys_content_t /www/t.txt
De forma predeterminada, esta modificación se elimina cuando se vuelve a etiquetar el sistema de archivos. Para que el cambio sea permanente, ejecute:
# semanage fcontext -a -t httpd_sys_content_t /www/t.txt # restorecon -v /www/t.txt
Para modificar las etiquetas de archivos de grupos de archivos, ejecute:
# semanage fcontext -a -t httpd_sys_content_t '/www(/.*)?' # restorecon -Rv /www
httpd_t
Amplíe la política de httpd_t
para permitir el acceso a ubicaciones de archivos adicionales:
# grep nginx /var/log/audit/audit.log | audit2allow -m nginx > nginx.te # cat nginx.te módulo nginx 1.0; requerir { tipo httpd_t; tipo predeterminado_t; tipo http_cache_port_t; clase tcp_socket nombre_conexión; clase archivo { leer getattr abrir }; } #============= httpd_t ============== permitir httpd_t predeterminado_t:archivo { leer getattr abrir }; #!!!! Este avc se puede permitir usando uno de estos booleanos: # httpd_can_network_relay, httpd_can_network_connect allow httpd_t http_cache_port_t:tcp_socket name_connect;
Para generar una política compilada, incluya la opción -M
:
# grep nginx /var/log/audit/audit.log | audit2allow -M nginx
Para cargar la política, ejecute semodule
-i
y luego verifique el éxito con semodule
-l
:
# semodule -i nginx.pp # semodule -l | grep nginx nginx 1.0
Este cambio persiste después de los reinicios.
De forma predeterminada, la configuración de SELinux no permite que NGINX escuche ( bind()
) puertos TCP o UDP distintos de los predeterminados que están en la lista de permitidos en el tipo http_port_t
:
# semanage puerto -l | grep http_port_t http_port_t tcp 80, 443, 488, 8008, 8009, 8443
Si intenta configurar NGINX para escuchar en un puerto no permitido (con la directiva listen
en el contexto http
, stream
o mail
en la configuración de NGINX), obtendrá un error cuando verifique ( nginx
-t
) o vuelva a cargar la configuración de NGINX, como lo indica esta entrada de registro de NGINX:
AAAA / MM / DD hh : mm : ss [emerg] 46123#0: error al enlazar() a 0.0.0.0:8001 (13: Permiso denegado)
Puede utilizar semanage
para agregar el puerto deseado (aquí, 8001) al tipo http_port_t
:
# semanage puerto -a -t http_port_t -p tcp 8001
Recargue NGINX con la nueva configuración.
# nginx -s recargar
Hay demasiados archivos abiertos
ErrorCuando se excede el límite en la cantidad de archivos abiertos ( RLIMIT_NOFILE
), aparece el siguiente mensaje en el registro de errores:
Hay demasiados archivos abiertos
En la mayoría de los casos, el proceso de trabajo de NGINX informa este error, pero no puede usar la directiva NGINXworker_rlimit_nofile
para aumentar el límite porque SELinux no permite la llamada del sistema setrlimit()
, como se informa en los siguientes mensajes en los registros de error y auditoría.
En /var/log/nginx/error.log para CentOS/RHEL 7.4+:
AAAA / MM / DD hh : mm : ss [alerta] 12066#0: setrlimit(RLIMIT_NOFILE, 2342) falló (13: Permiso denegado)
En /var/log/nginx/error.log para CentOS/RHEL 8.0+:
AAAA / MM / DD hh : mm : ss [alerta] 3327#0: setrlimit(RLIMIT_NOFILE, 65535) falló (1: Operación no permitida)
En /var/log/audit/audit.log para CentOS/RHEL 7.4+ y /var/log/messages para CentOS/RHEL 8.0+:
tipo=AVC msg=audit(1437731200.211:366): avc: denegado { setrlimit } para pid=12066 \ comm="nginx" scontext=system_u:system_r:httpd_t:s0 \
tcontext=system_u:system_r:httpd_t:s0 tclass=process
Para aumentar el límite, ejecute este comando como usuario root
:
$ setsebool -P httpd_setrlimit 1
Si el proceso maestro de NGINX informa el error, debe actualizar el archivo de unidad
systemd
para NGINX. Esto establece el límite de descriptores de archivo para los procesos maestro y de trabajo.
Cree un directorio para la configuración de nginx.service
:
$ mkdir /etc/systemd/system/nginx.service.d
Agregue las siguientes líneas a /etc/systemd/system/nginx.service.d/nofile_limit.conf :
[Servicio]LimitNOFILE=65535
Recargue la configuración del demonio systemd y reinicie NGINX:
$ systemctl daemon-reload $ systemctl restart nginx.service
Recursos adicionales
SELinux es una herramienta compleja y potente para administrar los permisos del sistema operativo. Información adicional está disponible en los siguientes documentos.
"Esta publicación de blog puede hacer referencia a productos que ya no están disponibles o que ya no reciben soporte. Para obtener la información más actualizada sobre los productos y soluciones F5 NGINX disponibles, explore nuestra familia de productos NGINX . NGINX ahora es parte de F5. Todos los enlaces anteriores de NGINX.com redirigirán a contenido similar de NGINX en F5.com.