Reducir la superficie de ataca de contenedores sin shell ni herramientas superfluas
Una guía práctica para construir imágenes de contenedor minimalistas con Landlock, seccomp y recompilación continua para mitigar riesgos CVE.

Las imágenes oficiales de contenedor suelen cargar con un peso muerto considerable. En el caso de PowerDNS Recursor, la imagen oficial basada en Debian ronda los 355 MB y contiene unos 7.500 archivos. Mike Cardwell decidió que esa exposición era innecesaria y documentó su proceso para crear una alternativa endurecida, priorizando la seguridad sobre la comodidad.
El enfoque comienza eliminando el entorno operativo completo. En lugar de empaquetar una distribución, el autor compila pdns-recursor estáticamente con Musl dentro de un contenedor Alpine temporal. El resultado final se copia a una imagen scratch, reduciendo el tamaño a 36 MB y dejando solo dos ejecutables. Al no incluir shell ni utilidades del sistema, un atacante que comprometa el proceso carece de herramientas básicas para moverse lateralmente o ejecutar comandos arbitrarios.
Para reforzar aún más el perímetro, se introdujo un programa iniciador escrito en C. Este proceso entrypoint utiliza la característica Landlock del kernel de Linux para aplicar políticas de arena (sandboxing) antes de ceder el control al recursor. Landlock restringe el acceso de lectura y escritura exclusivamente a las rutas necesarias para la configuración, bloqueando el acceso a directorios sensibles como /proc. También limita los puertos TCP y UDP a los que el proceso puede conectarse o vincularse, dificultando las comunicaciones con servidores de comando y control.
La restricción de llamadas al sistema es otro pilar de esta arquitectura. Mediante strace, se generó una lista blanca (seccomp.json) que permite únicamente las syscalls que la aplicación utiliza realmente. Esto bloquea accesos a interfaces como io_uring, bpf o keyctl, que a menudo son vectores de escalamiento de privilegios. Es crucial notar que este archivo de política no reside dentro de la imagen, sino que se referencia desde la configuración de Docker Compose o Kubernetes, lo que añade una capa de gestión externa pero evita su exposición en la capa de imagen.
La configuración de runtime incluye varias medidas defensivas estándar pero esenciales: mount de solo lectura para el sistema de archivos, un tmpfs pequeño con noexec para el socket de control, la eliminación de todas las capacidades de Linux (cap_drop: [ALL]) y la desactivación de la IPC si no es requerida. La opción no-new-privileges:true impide el escalamiento mediante binarios setuid.
Un aspecto operativo destacado es la estrategia de mantenimiento. Las imágenes tradicionales capturan las dependencias del momento de la construcción y permanecen estáticas. La solución propuesta utiliza un pipeline de CI en GitLab que reconstruye las imágenes diarias basándose en las versiones más recientes de los trenes estables de PowerDNS. Si上游如Debian o Alpine publican parches de seguridad para dependencias como OpenSSL, la próxima construcción del recursor los incorpora automáticamente. Esto significa que una etiqueta de versión puede ofrecer diferentes compilaciones con mejoras de seguridad a lo largo del tiempo, permitiendo a los operadores mantenerse actualizados contra CVEs sin reimplementar manualmente el contenedor cada vez que sale un parche menor.