Introducción
Los contenedores de Docker, en realidad, no son aplicaciones Sandbox, lo que significa que no se recomienda ejecutar aplicaciones aleatorias en el sistema como root con Docker. Debe tratar siempre un contenedor que ejecuta un servicio/proceso como un servicio/proceso que se ejecuta en el sistema host, y colocar todas las medidas de seguridad dentro del contenedor que coloca en el sistema host.
Vimos en el Capítulo 1, Introducción e Instalación , cómo Docker utiliza namespaces para la isolación. Los seis namespaces que utiliza Docker son Proceso, Red, Montaje, Nombre de host, Memoria compartida y Usuario. No todo en Linux está namespaced, por ejemplo, SELinux, Cgroups, Dispositivos ( /dev/mem , /dev/sd* ), y Módulos del kernel. Los sistemas de archivos bajo /sys , /proc/sys , /proc/sysrq-trigger , /proc/irq , y /proc/bus no están namespaced, pero se montan como de solo lectura por defecto con el tiempo de ejecución del contenedor containerD.
Para hacer que Docker sea un entorno seguro, se ha realizado mucho trabajo en el pasado reciente, y más trabajo está en marcha.
- Como las imágenes de Docker son el bloque de construcción básico, es muy importante que elijamos la imagen base correcta para empezar. Docker tiene este concepto de imágenes oficiales, que son mantenidas por Docker, el proveedor o alguien más. Si recuerda del Capítulo 2, Trabajando con contenedores de Docker , podemos buscar imágenes en Docker Hub utilizando la siguiente sintaxis:
$ docker search <nombre de la imagen>
Por ejemplo, considere el siguiente comando:
$ docker search ubuntu

Veremos una columna, OFICIAL , y si las imágenes son oficiales, veremos [OK] contra esa imagen en esa columna. Hay una característica en Docker que realiza la verificación de firma digital de las imágenes oficiales después de descargarlas. Si la imagen está manipulada, se nos notificará, pero no se impedirá que el usuario la ejecute.
NOTA
Puede encontrar más detalles sobre las imágenes oficiales en https://github.com/docker-library/official-images.
-
En Capítulo 6, API y SDK de Docker , vimos cómo podemos proteger la API remota de Docker, cuando el acceso al demonio de Docker se configura a través de TCP.
-
También podemos considerar desactivar la comunicación predeterminada entre contenedores sobre la red con
--icc=falseen el host de Docker; aunque los contenedores aún pueden comunicarse a través de enlaces, que anula la política predeterminada de DROP de iptables, se establecen con la opción--icc=false. -
También podemos establecer restricciones de recursos de Cgroups, a través de las cuales podemos prevenir ataques de Negación de Servicio ( DoS ) a través de limitaciones de recursos del sistema.
-
Docker aprovecha el dispositivo especial, Cgroups, que nos permite especificar qué nodos de dispositivo se pueden utilizar dentro del contenedor. Bloquea los procesos para crear y utilizar nodos de dispositivo que podrían utilizarse para atacar el host.
-
Cualquier nodo de dispositivo precreado en la imagen no se puede utilizar para hablar con el kernel porque las imágenes se montan con la opción nodev.
A continuación, se presentan algunas pautas (que pueden no ser completas) que puede seguir para lograr un entorno de Docker seguro:
-
Ejecuta servicios como no root y trata el root en el contenedor, así como fuera del contenedor, como root.
-
Utiliza imágenes de partes confiables para ejecutar el contenedor; evita utilizar la opción
-insecure-registry=[]. -
No ejecutes contenedores aleatorios del registro de Docker o de cualquier otro lugar.
-
Mantén el kernel del host actualizado.
-
Evita utilizar
--privilegedsiempre que sea posible, y reduce los privilegios del contenedor lo antes posible. -
Configura el Control de Acceso Obligatorio ( MAC ) a través de SELinux o AppArmor.
-
Recopila registros para auditorías.
-
Realiza auditorías regulares.
-
Ejecuta contenedores en hosts que estén diseñados específicamente para ejecutar contenedores. Considera utilizar Project Atomic, CoreOS o soluciones similares.
-
Monta dispositivos con la opción
--deviceen lugar de utilizar la opción--privilegedpara utilizar dispositivos dentro del contenedor. -
Prohíbe SUID y SGID dentro del contenedor.
Docker y el Centro de Seguridad de Internet (http://www.cisecurity.org/) publicaron una guía de mejores prácticas para la seguridad de Docker, que cubre la mayoría de las pautas anteriores y más en https://blog.docker.com/2015/05/understanding-docker-security-and-best-practices/.
En Capítulo 1, Introducción e Instalación , describimos cómo instalar Docker en CentOS 7.5. Utilicemos esa instalación predeterminada para realizar un experimento:
- Desactiva SELinux utilizando el siguiente comando:
$ sudo setenforce 0
- Crea un usuario y agrégalo al grupo de Docker predeterminado para que el usuario pueda ejecutar comandos de Docker sin
sudo:
$ sudo useradd dockertest
$ sudo passwd dockertest
$ sudo groupadd docker
$ sudo gpasswd -a dockertest docker
- Inicia sesión utilizando el usuario que creamos anteriormente y ejecuta un contenedor de la siguiente manera:
$ su - dockertest
$ docker container run -it -v /:/host alpine ash
- Desde el contenedor,
chroota/hosty ejecuta el comando de apagado:
$ chroot /host
$ shutdown

Como podemos ver, un usuario en un grupo de Docker puede apagar el sistema host. Docker actualmente no tiene control de autorización, por lo que si puede comunicarse con el socket de Docker, se le permite ejecutar cualquier comando de Docker. Es similar a /etc/sudoers :
USERNAME ALL=(ALL) NOPASSWD: ALL
Esto no es bueno. Veamos cómo podemos protegernos contra esto y más en el resto del capítulo.