TUTORIAL: ¿Cómo c*rajo se usa SELinux?



NOTA: El título se debe a que comúnmente cuando una persona cambia de una distribución que no usa un MAC (o al menos no uno tan "involucrado" como SELinux) a una que sí lo hace, generalmente de primera instancia se empieza a "dar de topes" tratando de saber porqué X o Y no funcionan en su setup habitual, para al final desactivar SELinux y ver que ése era el problema desde un inicio. Dicho título es entonces una alusión a lo incomprendida que está esta herramienta de seguridad por aquellos que no están acostumbrados a usarla.

So... Todos los que usamos Fedora, CentOS, RHEL y/o derivados, conocemos a SELinuxSecurity-Enhanced Linux, que básicamente se trata de un módulo de seguridad para el Kernel mismo que trabaja por medio de pólizas. En términos sencillos, SELinux es un programa similar a un híbrido de antivirus/firewall y protege al sistema de comportamientos inesperados por medio de una implementación MAC (Mandatory Access Control); Piensa algo así como la ventana esta molesta de Windows (¿user account control creo que se llama su implementación?):


Pero de hecho útil, poco molesto, programable y con muchísimas más funcionalidades añadidas. Cabe destacar que no voy a hablar de SELinux a fondo aquí (¡Lo creó la NSA! y sus políticas de seguridad son avaladas y aprobadas por el departamento de defensa de EEUU, so se trata de un software revisado a fondo que se usa día a día en equipos de misión crítica); solo haré un pequeño tutorial de cómo manejarlo a nivel básico en tus equipos y/o servidores.


Hasta ahora ya entendimos que básicamente SELinux impide que un programa/proceso se comporte de manera "extraña" (haga cosas que se consideran potencialmente inseguras o que comúnmente no debería de hacer) tal y como se muestra en la imagen de arriba: Sin un MAC presente, el perro podría fácilmente comerse la comida del gato sin problemas y aunque esto no se considera un escenario "inseguro" per sé (debido a que las probabilidades de que dicha comida le haga daño son mínimas); esto no es algo que debería estar pasando en primer lugar... El perro tiene su propia comida disponible:


Imágenes del SELinux coloring book

Entonces bien, cada que pasa algo que "no se supone debería pasar" recibimos una alerta de SELinux que notaremos en las notificaciones del sistema (identificándola con el ícono distintivo de la herramienta) estas alertas, ya cuando las abrimos se ven así:


En el caso de la alerta de arriba, el problema está en que tengo configurado NGINX para servir una aplicación que está escuchando en el puerto 3000, pero NGINX no tiene permiso por defecto para ver lo que está sucediendo en ese puerto con el fin de llevar a cabo su trabajo tal y como yo se lo indiqué. Esto resulta en lo siguiente cuando alguien visita dicha aplicación:


Si expandimos la alerta, El asistente de alertas de SELinux nos mostrará las posibles soluciones, (una temporal y una permanente):


En este caso la que nos importa es la permanente (la de abajo) y si hacemos lo que nos indica:

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

Nótese cómo cambié mypol por nginx en el comando recomendado, así es como debes permitir nuevas políticas, con un nombre distintivo para cada excepción.

Veremos que pasa lo siguiente en nuestra consola:


Y más tarde, ya podremos visitar la aplicación deseada normalmente:


Para los que estén trabajando en un servidor/equipo sin GUI, generar un reporte legible de las alertas se hace con el siguiente comando:

# echo "Time: $(date)" >> /var/log/selinux-alerts.log && sealert -a /var/log/audit/audit.log > /var/log/selinux-alerts.log

Después podemos leer dicho archivo en la CLI con:

# cat /var/log/selinux-alerts.log

Ahora bien, si queremos listar las políticas que tenemos activas actualmente en el sistema (llamémosles excepciones), podemos correr:

# semodule -l

para saber si tenemos una política y/o excepción específica habilitada, usamos:

# semodule -l | grep mypol

Cambiando mypol por el nombre de la política/excepción que estemos buscando.

Para desactivar/eliminar estas excepciones/políticas, corremos:

# semodule -r mypol nginx

Reemplazando nginx y mypol por los nombres de las excepciones y/o políticas que queramos deshabilitar respectivamente.

Otro caso interesante sería si quisiéramos permitir el acceso a un puerto no predeterminado en nuestro sistema (conexiones SSH entrantes a otro puerto que no sea el 22 por ejemplo), esto en el caso de SSH (después de abrir el puerto deseado en el firewall previamente) lo haríamos así:

# semanage port -a -t ssh_port_t -p tcp puerto

Reemplazando puerto por el número de puerto deseado.

Para conocer la lista de puertos permitidos (y los nombres adecuados para modificarlos) ejecutamos:

# semanage port -l

Y pues bueno, eso es todo... Así es como se usa SELinux a nivel básico. Ya no tienen porqué desactivarlo o ponerlo en modo permisivo cuando les cause problemas, simplemente era cosa de entenderlo.

Extra: SELinux Sandbox

Cómo montar un entorno aislado usando SELinux Sandbox

P.D. Si quieren conocer más a fondo SELinux y cómo utilizarlo (¡es todo un estuche de monerías!) les recomiendo el libro The SELinux Notebook que nos mencionan en la wiki del proyecto.