Estoy trabajando en un proyecto que implementa simulaciones distribuidas: el código arbitrario se ejecuta en múltiples nodos y los resultados luego se recopilan y se agregan.
Cada nodo es una instancia de una máquina virtual Ubuntu Linux y ejecuta un proceso maestro que se encarga de reenviar el código para que se ejecute a varios procesos de trabajo (1 para cada núcleo).
Esta pregunta trata sobre cómo asegurarse de que cada trabajador opere en un entorno de espacio aislado sin recurrir al uso de una instancia de máquina virtual para cada uno de ellos. Los requisitos exactos para los trabajadores son:
- fs : sin permiso de escritura, permiso de solo lectura limitado a un solo directorio (y subcarpetas)
- net : solo se permiten comunicaciones locales (IPC, TCP, lo que sea ...)
- mem : límite de uso de memoria (sin memoria de intercambio) matar si supera el límite de memoria
- CPU : solo se permite 1 núcleo, matar si se supera el límite de tiempo
No se deben imponer otras limitaciones: el trabajador debe poder cargar bibliotecas dinámicas (desde la carpeta de solo lectura), generar nuevos subprocesos o procesos, llamar a la función del sistema, ecc ecc, pero los límites deben ser heredados por las entidades generadas / cargadas y debe aplicarse de manera sumaria (por ejemplo, no podemos hacer que un trabajador genere dos subprocesos que usan 800 MB cada uno, el límite de memoria para ese trabajador es de 1 GB).
No hace falta decir que no debería haber forma de que el trabajador eleve sus derechos.
Pasé un tiempo considerable revisando las alternativas disponibles (SELinux, AppArmor, cgroups, ulimit, espacios de nombres de Linux, LXC, Docker, ...) para encontrar la solución más simple que satisfaga mis requisitos, pero mi experiencia en el campo es limitada.
Conocimiento actual: LXC y Docker son un poco pesados para mi caso de uso y no son completamente seguros 1 . AppArmor preferible a SELinux debido a una configuración más fácil, utilícelo para fs y restricciones de red; cgroups preferible a ulimit (que opera en un solo proceso), lo usó para restricciones mem y cpu.
¿Es esta la forma más sencilla de lograr mi objetivo? ¿Puedo usar AppArmor o cgroups exclusivamente? ¿Hay algún agujero de seguridad obvio en mi modelo? La directriz debería ser "trabajador autorizado para derribar a sí mismo, pero nada más" .
Respuestas:
Sí, puede usar cgroups y SELinux / AppArmor exclusivamente para monitorear y controlar el código arbitrario que ejecutará.
Con cgroups, puede hacer lo siguiente:
cpuset
subsistemamemory
subsistema, rastreando incluso las horquillas. Consulte https://github.com/gsauthof/cgmemtime para ver un ejemplo.lo
con elnet_prio
subsistema.Y con SELinux / AppArmor, puede limitar el acceso de lectura / escritura del proceso.
Nota: no estoy familiarizado con AppArmor, pero es un sistema de control de acceso obligatorio (MAC), lo que significa que proteger la escritura y la lectura es su trabajo.
El uso de estos sistemas es cuestión de escribir las configuraciones adecuadas. Por supuesto, todo esto es mucho más fácil decirlo que hacerlo. Aquí hay algunos enlaces de referencia para comenzar:
¡Buena suerte!
fuente
Descartaría SELinux para AppArmor solo si estuviera usando Ubuntu . (realmente bastante difícil)
LXC no es seguro por sí mismo. Si necesita seguridad, debe usarlos a través de libvirt (basado en SELinux MLS ).
Su problema es infinito, así que no intente encontrar ninguna solución inmediata y sin tiempo infinito, recuerde que incluso kernel.org fue expulsado y recientemente el FBI declaró que alguien ha estado usando sus sistemas durante años sin ser detectado hasta ahora.
Iré con LXC / libvirt para una seguridad bastante buena o probaré los "nuevos" contenedores intel clear , que usan una VM muy ligera para su contenedor con un uso claro de DAX / KSM (no los he probado pero se ven muy prometedor de hecho).
Si le preocupa la explotación del kernel, la seguridad es su solución, pero tendría que integrarla con la solución de su contenedor (seguro, dolores de cabeza).
Por lo tanto, no es una tarea fácil, LXC / libvirt son realmente geniales, pero tal vez los contenedores transparentes sean el camino a seguir.
¿Estibador? No usé / no usaría docker para más que pruebas locales cuando no había una caja vagabunda disponible, necesitan mucho más trabajo y una comunidad mucho mejor.
Por supuesto, los contenedores systemd también son agradables, pero supongo que no les gustan o los quieren porque ni siquiera los mencionó y no son una solución independiente del proveedor.
Si desea algo "más fácil" y más aficionado, puede consultar Firejail , lo he estado usando para algunas "aplicaciones" de escritorio y hace el trabajo (es bastante fácil crear la plantilla para su aplicación personalizada, use "privado" se monta en la parte superior de sus directorios y restringe la red solo para uso local, los procesos generados heredan para el padre y continúan ...).
Saludos y diviértete sin volverte loco. ;)
fuente
seccomp-bpf es otra opción que funciona bien para OpenSSH, vsftpd y Chromium, solo tiene exit (), sigreturn (), read (), también usa write (), aunque permite el filtrado de llamadas al sistema utilizando reglas configurables de Berkeley Packet Filter. También podría usarse junto con cgroups para memoria, CPU, etc.
https://wiki.mozilla.org/Security/Sandbox/Seccomp
fuente
Es posible que desee examinar los sistemas de computación grid. En particular, BOINC ( http://boinc.berkeley.edu ) verifica casi todas sus casillas.
Creo que opera en sus parámetros como tal:
fs: puede leer / escribir en su propio directorio, en ningún otro lugar
net: se puede configurar para permitir solo el acceso de red a su servidor BOINC, pero no es el predeterminado IIRC de fábrica
mem: sí, límites de memoria separados para máquinas inactivas y no inactivas
cpu: sí, incluso puedo decir "no ejecutar si la computadora no está inactiva"
fuente