Tengo solicitudes de reenvío de nginx a gunicorn a través de un socket unix en /run/gunicorn/socket
. Por defecto, SELinux no permite este comportamiento:
grep nginx /var/log/audit/audit.log
type=SERVICE_START msg=audit(1454358912.455:5390): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=nginx comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
type=AVC msg=audit(1454360194.623:7324): avc: denied { write } for pid=9128 comm="nginx" name="socket" dev="tmpfs" ino=76151 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=sock_file
type=SYSCALL msg=audit(1454360194.623:7324): arch=c000003e syscall=42 success=no exit=-13 a0=c a1=1f6fe58 a2=6e a3=7ffee1da5710 items=0 ppid=9127 pid=9128 auid=4294967295 uid=995 gid=993 euid=995 suid=995 fsuid=995 egid=993 sgid=993 fsgid=993 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null)
type=AVC msg=audit(1454361591.701:13343): avc: denied { connectto } for pid=9128 comm="nginx" path="/run/gunicorn/socket" scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:system_r:initrc_t:s0 tclass=unix_stream_socket
type=SYSCALL msg=audit(1454361591.701:13343): arch=c000003e syscall=42 success=no exit=-13 a0=c a1=1f6fe58 a2=6e a3=7ffee1da5950 items=0 ppid=9127 pid=9128 auid=4294967295 uid=995 gid=993 euid=995 suid=995 fsuid=995 egid=993 sgid=993 fsgid=993 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null)
En todas partes que miro (por ejemplo, aquí y aquí ), las instrucciones para permitir que este haga una solicitud a nginx, SELinux rechace la solicitud y luego la ejecute audit2allow
para permitir futuras solicitudes. No puedo entender ninguno chcon
o semanage
comando que permita este comportamiento explícitamente.
¿Es esta la única forma? Parece ridículo que no se pueda configurar una política que permita que nginx escriba en un socket sin que primero se haya denegado un intento y luego se ejecute una herramienta que permita cosas que fueron denegadas. ¿Cómo sabes exactamente qué se está habilitando? ¿Cómo se supone que esto funciona si está configurando máquinas bajo automatización?
Estoy usando CentOS 7.
Respuestas:
Pues no, SELinux es un control de acceso obligatorio, las cosas están denegadas por defecto y tienes que permitir explícitamente algo. Si los autores de la política no han considerado una pila particular (franken) o los autores de un demonio no lo han hecho una política escrita y consciente de SELinux, entonces usted está solo. Debe analizar qué están haciendo sus servicios y cómo están interactuando con SELinux y elaborar su propia política para permitirlo. Hay herramientas disponibles para ayudarlo a audit2why , audit2allow , etc.
No, pero depende de lo que intente hacer y de cómo intente hacerlo en cuanto a cuál es la solución. Por ejemplo, es posible que desee vincular nginx (httpd_t) al puerto 8010 (puerto no reservado_t). Cuando comienzas nginx falla
y usted (eventualmente) mira en el registro de auditoría y encuentra
Puede ejecutar esto a través de audit2alllow y aceptar ingenuamente sus hallazgos
que luego permite que httpd_t se conecte a cualquier puerto tcp. Esto puede no ser lo que quieres.
Puede usar sesearch para investigar la política y ver a qué tipos de puertos puede acceder httpd_t name_bind
Entre otros tipos, http_t puede unirse a http_port_t. Ahora puedes usar semanage para cavar un poco más profundo.
El puerto 8010 no está en la lista. Como queremos que nginx se una al puerto 8010, no es irracional agregarlo a la lista http_port_t
Ahora se permitirá a nginx name_bind al puerto 8010 y no a todos los puertos tcp como se indicó anteriormente.
Los cambios en la política son bastante fáciles de leer, ejecutando sus mensajes arriba a través de audit2allow obtenemos
que parecen bastante explicativos.
El primero de ellos se refiere al archivo con inum 76151. Puede usar find para obtener su nombre (find / -inum 76151) y luego usar
semanage fcontext -a -t ...
para cambiar la política y restorecon para arreglar el contexto.El segundo se refiere a
/run/gunicorn/socket
que nuevamente tiene el contexto equivocado. Usando sesearch podemos ver que http_t puede conectarse a unix_stream_sockets de tipo (entre otros) http_t. Entonces podemos cambiar el contexto en consecuencia, por ejemploEsto establece el contexto de / run / gunicorn y el árbol | archivos debajo de él a httpd_t.
Debe analizar el sistema y realizar los cambios apropiados en la prueba. Luego, utiliza sus herramientas de automatización para implementar los cambios, Puppet y Ansible tienen soporte para esto.
Por supuesto, puede hacerlo todo en producción con SElinux configurado en permisivo. Recopile todos los mensajes, analícelos, decida sus cambios y despliéguelos.
Hay mucho más que saber sobre SELinux, pero ese es el límite de mis habilidades, Michael Hampton es mejor y Mathew Ife es mucho mejor de nuevo, pueden tener más para agregar.
fuente
allow httpd_t httpd_sys_content_t:sock_file write;
no me explica tanto como esperaba. Lo que se esta diciendo que la política de que las necesidades de archivo que se cambió a (es decir, lo que sucede después-t
en elsemanage
comando?semanage
comandos directamente. Necesito agregar un--add
argumento.httpd_var_run_t
como Michael Hampton señaló a continuación, elaudit2allow
mensaje es:allow httpd_t var_run_t:sock_file write;
var_run_t
nohttpd_var_run_t
.audit2allow
diceallow httpd_t var_run_t:sock_file write;
El tipo que desea usar no lo es
httpd_sys_content_t
. Esto es para archivos estáticos que el servidor web debe servir a los agentes de usuario.Para un socket utilizado para la comunicación entre procesos, el tipo que está buscando es
httpd_var_run_t
.Sin embargo, tenga en cuenta que debido a que ejecutó gunicorn sin restricciones, puede haber problemas adicionales para comunicarse con él.
fuente
Probé las respuestas anteriores sin éxito, en mi caso estoy usando un servidor nginx como interfaz para una aplicación uwsgi que usa sockets unix para comunicarlos, mi sistema operativo es un servidor Fedora 26.
Los sockets de Unix se crean en el directorio
/var/local/myapp
:Para configurar SELinux tuve que agregar el tipo de contexto:
httpd_sys_rw_content_t
fuente