Skip to content

Commit 293efa0

Browse files
committed
Refactor README.md to streamline security options section, removing redundant explanations and examples for seccomp and AppArmor, while retaining essential information for clarity.
1 parent 4082786 commit 293efa0

1 file changed

Lines changed: 3 additions & 293 deletions

File tree

01-contenedores/contenedores-ii/README.md

Lines changed: 3 additions & 293 deletions
Original file line numberDiff line numberDiff line change
@@ -172,291 +172,6 @@ Las variables de entorno permiten configurar aplicaciones sin modificar la image
172172
- `DB_*`: Configuración de base de datos
173173
- `APP_*`: Configuraciones específicas de la aplicación
174174

175-
176-
177-
### 🔒 **Opciones de seguridad (--security-opt)**
178-
179-
Configuran políticas de seguridad del contenedor y controlan qué acceso tiene el contenedor a las llamadas del sistema.
180-
181-
Pero espera, ¿qué son **seccomp** y **AppArmor**? Si es la primera vez que lo escuchas, no te preocupes, es más sencillo de lo que parece:
182-
183-
#### 📚 **¿Qué es seccomp?**
184-
185-
**seccomp** (del inglés "Secure Computing") es un **filtro de seguridad a nivel del kernel de Linux** que actúa como un intermediario entre tus programas y el sistema operativo.
186-
187-
Piénsalo así:
188-
- Tu aplicación quiere hacer algo (abrir un archivo, crear un proceso, acceder a la red, etc.)
189-
- El kernel necesita ejecutar una **"llamada del sistema"** (syscall) para hacer eso
190-
- **seccomp intercepta esa llamada** y comprueba si está permitida según sus reglas
191-
- Si está permitida → se ejecuta ✅
192-
- Si NO está permitida → se bloquea 🚫
193-
194-
**Ejemplo real:**
195-
- Firefox necesita acceder a gráficos de bajo nivel → necesita muchas syscalls especiales
196-
- Una aplicación web normal → solo necesita syscalls básicas (leer archivos, conectar a red, crear procesos)
197-
198-
Docker por defecto aplica un perfil seccomp que **solo permite las syscalls seguras y necesarias**, bloqueando operaciones peligrosas que podrían comprometer la seguridad del sistema.
199-
200-
#### 📚 **¿Qué es AppArmor?**
201-
202-
**AppArmor** es un **sistema de control de acceso obligatorio (MAC)** que define qué puede y qué no puede hacer cada programa.
203-
204-
Piénsalo como un "permiso de acceso" muy granular:
205-
- Este programa **puede** leer archivos de `/usr/share/`
206-
- Este programa **no puede** acceder a `/etc/shadow` (archivo de contraseñas)
207-
- Este programa **no puede** modificar archivos en `/bin/`
208-
209-
Docker aplica por defecto un perfil AppArmor llamado `docker-default` que restringe las operaciones de los contenedores.
210-
211-
#### 🔄 **seccomp vs AppArmor - ¿Cuál es la diferencia?**
212-
213-
| Aspecto | seccomp | AppArmor |
214-
|--------|---------|----------|
215-
| **Qué filtra** | Llamadas del sistema (syscalls) | Acceso a archivos, red, etc. |
216-
| **Nivel** | Kernel (muy bajo nivel) | Sistema de archivos y red |
217-
| **Ejemplo bloqueo** | Evita que crees procesos nuevos | Evita que leas `/etc/shadow` |
218-
| **Overhead** | Muy bajo | Bajo |
219-
220-
Ambos trabajan juntos para crear múltiples capas de seguridad.
221-
222-
#### 🧪 **Ejemplo práctico 1: seccomp - Bloqueando operaciones peligrosas**
223-
224-
**Analogía simple:** seccomp es como un portero que ve qué intenta hacer el contenedor y le dice "sí" o "no" a nivel del kernel.
225-
226-
**Prueba esta comparación:**
227-
228-
```bash
229-
# ✅ CONTENEDOR NORMAL (CON seccomp por defecto)
230-
# La mayoría de operaciones funcionan perfectamente
231-
docker run --rm alpine sh -c 'echo "Hola" > /tmp/test.txt && cat /tmp/test.txt'
232-
# Funciona sin problemas porque crear archivos está PERMITIDO
233-
234-
# ❌ OPERACIÓN PELIGROSA BLOQUEADA (CON seccomp por defecto)
235-
# Intentar usar strace (que requiere ptrace) - bloqueado por seguridad
236-
docker run --rm ubuntu bash -c 'apt-get update -qq && apt-get install -y strace -qq && strace -e trace=ptrace echo "test"'
237-
# Output: strace: trace: execve failed: Operation not permitted
238-
# ❌ "Operation not permitted" = ptrace está BLOQUEADO por seccomp
239-
240-
# ✅ MISMA OPERACIÓN PERMITIDA (SIN seccomp - security-opt seccomp=unconfined)
241-
# Desactivamos seccomp = permitimos todas las syscalls incluyendo ptrace
242-
docker run --rm --security-opt seccomp=unconfined ubuntu bash -c 'apt-get update -qq && apt-get install -y strace -qq && strace -e trace=ptrace echo "test"'
243-
# Output: echo(1, "test", 2) = 5
244-
# ✅ Funciona - ptrace está PERMITIDO (pero es peligroso)
245-
```
246-
247-
**¿Qué ves?**
248-
- **Por defecto**: seccomp bloquea operaciones peligrosas (ptrace) ✅ Seguro
249-
- **Sin seccomp**: Se permite todo, incluso lo peligroso ⚠️ Menos seguro
250-
251-
**📌 ¿Qué es ptrace y por qué está bloqueado?**
252-
253-
`ptrace` es una syscall (llamada del sistema) que permite a un proceso **"espiar" o "debuggear" otros procesos**:
254-
255-
- **Usos legítimos**: Debuggers (gdb, lldb), profilers, herramientas de análisis
256-
- **Usos maliciosos**: Un contenedor podría usarlo para:
257-
- Inyectar código en otros procesos
258-
- Leer la memoria de otros procesos (¡y encontrar contraseñas!)
259-
- Modificar el comportamiento de otros procesos
260-
- Escapar del contenedor accediendo a procesos del host
261-
262-
Por eso Docker **bloquea ptrace por defecto** con seccomp. Si necesitas debuggear o usar herramientas de profiling dentro de un contenedor de desarrollo, es cuando desactivarías seccomp (`--security-opt seccomp=unconfined`), pero **nunca en producción**.
263-
264-
---
265-
266-
#### 🧪 **Ejemplo práctico 2: AppArmor - Bloqueando acceso a archivos sensibles**
267-
268-
**Analogía simple:** AppArmor es como un guardaespaldas que vigila a dónde puede ir el contenedor.
269-
270-
**Prueba esta comparación:**
271-
272-
```bash
273-
# ✅ ACCESO NORMAL A ARCHIVOS (CON AppArmor por defecto)
274-
# Puedes leer archivos normales sin problema
275-
docker run --rm alpine cat /etc/hostname
276-
# Funciona perfectamente
277-
278-
# ❌ ACCESO A ARCHIVOS SENSIBLES BLOQUEADO (CON AppArmor por defecto)
279-
# Pero los archivos realmente sensibles están protegidos
280-
docker run --rm -v /etc:/etc:ro alpine cat /etc/shadow
281-
# ❌ Permission denied - AppArmor lo bloquea incluso si le das acceso al volumen
282-
283-
# ✅ MISMO ARCHIVO AHORA ACCESIBLE (SIN AppArmor - security-opt apparmor=unconfined)
284-
# Desactivamos AppArmor = quitamos la protección
285-
docker run --rm --security-opt apparmor=unconfined -v /etc:/etc:ro alpine cat /etc/shadow
286-
# ✅ Funciona - AppArmor no está bloqueándolo (pero es peligroso)
287-
```
288-
289-
**¿Qué ves?**
290-
- **Por defecto**: AppArmor protege archivos sensibles ✅ Seguro
291-
- **Sin AppArmor**: Se permite acceder a todo ⚠️ Menos seguro
292-
293-
---
294-
295-
**📌 Conclusión simple:**
296-
- **seccomp**: "¿Qué operaciones de bajo nivel puedes hacer?" (Por defecto: solo las seguras)
297-
- **AppArmor**: "¿A dónde puedes ir?" (Por defecto: solo a lugares seguros)
298-
299-
Ambos juntos = contenedor seguro por defecto. Desactívalo solo si realmente lo necesitas.
300-
301-
---
302-
303-
**📝 Detalles adicionales de AppArmor:**
304-
305-
AppArmor también protege directorios del sistema:
306-
307-
```bash
308-
# CON AppArmor (por defecto - bloquea escritura en /sys)
309-
docker run --rm alpine sh -c 'echo "test" > /sys/test.txt'
310-
# ❌ Permission denied - no puedes escribir en /sys
311-
312-
# SIN AppArmor (permite escritura)
313-
docker run --rm --security-opt apparmor=unconfined alpine sh -c 'echo "test" > /sys/test.txt'
314-
# ✅ Funciona (aunque /sys sea read-only, AppArmor no lo bloquea a nivel MAC)
315-
```
316-
317-
---
318-
319-
**✅ Prueba los comandos tú mismo:**
320-
321-
Si quieres ver la diferencia real, ejecuta estos comandos en tu máquina:
322-
323-
```bash
324-
# 1. Intenta acceder a /etc/shadow (archivo de contraseñas)
325-
# CON protección (AppArmor):
326-
docker run --rm -v /etc:/etc:ro alpine cat /etc/shadow 2>&1 | head -1
327-
# Probablemente: "cat: can't open '/etc/shadow': Permission denied"
328-
329-
# SIN protección (desactivamos AppArmor):
330-
docker run --rm --security-opt apparmor=unconfined -v /etc:/etc:ro alpine cat /etc/shadow 2>&1 | head -1
331-
# Funciona - ¡ve el contenido del archivo!
332-
333-
# 2. Conclusión: AppArmor protege archivos sensibles automáticamente
334-
```
335-
336-
```bash
337-
--security-opt seccomp=unconfined # Deshabilita el filtro de llamadas del sistema
338-
--security-opt apparmor=unconfined # Deshabilita AppArmor
339-
--security-opt no-new-privileges # Evita escalada de privilegios
340-
```
341-
342-
**📋 Valores por defecto (cuando no especificas nada):**
343-
344-
Por defecto, Docker aplica configuraciones **seguras y restrictivas**:
345-
346-
| Opción | Por defecto | Qué significa |
347-
|--------|-------------|---------------|
348-
| **seccomp** | `default` (restrictivo) | Docker aplica un perfil de seccomp que filtra llamadas del sistema peligrosas. Protege contra ataques a nivel de kernel |
349-
| **apparmor** | `docker-default` | Se aplica el perfil de AppArmor específico de Docker que limita operaciones del contenedor |
350-
| **privileges** | No permitidos | Los procesos NO pueden escalar privilegios (cambiar de usuario/grupo) |
351-
352-
**� Entendiendo cada opción:**
353-
354-
- **`seccomp=unconfined`**: Desactiva el filtro de seguridad de llamadas del sistema (syscalls).
355-
- **En la práctica**: Tu contenedor puede hacer prácticamente cualquier cosa a nivel del kernel, incluyendo operaciones peligrosas que podrían comprometer el host.
356-
- **Cuándo necesitas esto**: Aplicaciones gráficas como Firefox, Chrome o herramientas de debugging de bajo nivel que requieren acceso directo al kernel (ej: Frida, GDB con capacidades especiales).
357-
- **El coste**: **⚠️ Reduce significativamente la seguridad**. Un atacante podría usar syscalls peligrosas para escapar del contenedor o comprometer el host.
358-
- **Si no lo especificas**: Docker mantiene el filtro por defecto (seguro), bloqueando syscalls peligrosas como `ptrace`, `kexec`, `bpf`, etc.
359-
- **Ejemplo**: Firefox necesita `mmap` con permisos especiales y acceso a `/dev/dri/` (gráficos), por eso requiere `seccomp=unconfined`.
360-
361-
- **`apparmor=unconfined`**: Desactiva AppArmor (el sistema de control de acceso obligatorio de Linux).
362-
- **En la práctica**: Sin AppArmor, tu contenedor tiene acceso mucho más permisivo al sistema de archivos y puede acceder a más recursos.
363-
- **Cuándo necesitas esto**: Raramente. La mayoría de aplicaciones funcionan bien con el perfil `docker-default`. Solo en casos muy específicos donde necesites acceso a archivos o directorios que AppArmor bloquea.
364-
- **El coste**: Aumenta la superficie de ataque. Un contenedor malicioso podría acceder a más recursos del sistema.
365-
- **Si no lo especificas**: Se aplica el perfil `docker-default`, que es una buena combinación de seguridad y funcionalidad.
366-
- **Diferencia respecto a seccomp**: Mientras seccomp filtra *qué* se puede hacer a nivel del kernel, AppArmor filtra *a dónde* se puede acceder (archivos, puertos, etc.).
367-
368-
- **`no-new-privileges`**: Evita que procesos dentro del contenedor puedan **escalar privilegios** (cambiar de usuario/grupo o ganar más permisos).
369-
- **En la práctica**: Un proceso que corre como usuario normal (ej: www-data) NO puede convertirse en root, incluso si encuentra una vulnerabilidad en setuid binaries.
370-
- **Ejemplo de ataque bloqueado**: Sin `no-new-privileges`, un atacante podría aprovechar un binario setuid para escalar a root. Con esta opción, se previene.
371-
- **Caso de uso**: Aplicaciones que no necesitan cambiar de usuario durante su ejecución (la mayoría).
372-
- **El coste**: Muy bajo. Principalmente la restricción de que no puedas usar `sudo` o funcionalidades que requieran cambio de usuario dentro del contenedor.
373-
- **Si no lo especificas**: Este es el **por defecto** en Docker, así que tu aplicación ya está protegida contra escalada de privilegios.
374-
375-
**⚠️ Importante**: `seccomp=unconfined` se usa para apps gráficas que necesitan acceso completo al sistema, pero reduce la seguridad. Solo úsalo cuando sea absolutamente necesario.
376-
377-
**💡 Recomendación**: La configuración por defecto de Docker es segura. Mantén la restricción si tu aplicación no necesita acceso de bajo nivel. Solo desactívalo cuando sea necesario, y siempre como última opción después de otros intentos.
378-
379-
#### 🎯 **Resumen: Las tres capas de seguridad**
380-
381-
Docker proporciona tres capas de seguridad que trabajan juntas:
382-
383-
1. **seccomp**: ¿Qué syscalls (operaciones de kernel) puedo ejecutar?
384-
- Por defecto: Bloqueado (muy restrictivo)
385-
- Activado en: Aplicaciones gráficas (Firefox, Chrome), debugging de bajo nivel
386-
2. **AppArmor**: ¿A qué archivos, puertos y recursos puedo acceder?
387-
- Por defecto: Perfil `docker-default` (restrictivo pero funcional)
388-
- Raramente necesitas desactivarlo
389-
3. **no-new-privileges**: ¿Puedo cambiar de usuario/grupo para ganar más permisos?
390-
- Por defecto: Desactivado (protegido contra escalada)
391-
- Previene que un atacante use vulnerabilidades para convertirse en root
392-
393-
**Analogía**: Es como entrar en una escuela:
394-
- **seccomp** = "¿Qué actividades puedo hacer?" (solo las permitidas por la dirección)
395-
- **AppArmor** = "¿A qué lugares puedo acceder?" (aulas permitidas, no la directiva)
396-
- **no-new-privileges** = "¿Puedo pretender ser un profesor?" (no, el sistema lo bloquea)
397-
398-
Todas juntas crean un contenedor **muy restringido pero funcional** que es seguro por defecto.
399-
400-
**Ejemplos de uso:**
401-
402-
```bash
403-
# Contenedor seguro (sin especificar nada, usa valores por defecto)
404-
docker run -d --name mi-app mi-app:latest
405-
# ✅ Tiene: seccomp restrictivo + apparmor + no-new-privileges
406-
407-
# Para una aplicación gráfica que necesita acceso completo
408-
docker run -d \
409-
--security-opt seccomp=unconfined \
410-
--name firefox \
411-
lscr.io/linuxserver/firefox:latest
412-
# ⚠️ Menos seguro, pero necesario para apps gráficas
413-
414-
# Para una aplicación de debugging que necesita más permisos
415-
docker run -d \
416-
--security-opt seccomp=unconfined \
417-
--security-opt apparmor=unconfined \
418-
--name debug-app \
419-
mi-app-debug:latest
420-
# ⚠️ Máximo permiso (usar solo para debugging)
421-
422-
# Para una aplicación que quieres mantener segura (explícitamente)
423-
docker run -d \
424-
--security-opt no-new-privileges \
425-
--name secure-app \
426-
mi-app:latest
427-
# ✅ Especificamos explícitamente que no hay escalada de privilegios
428-
```
429-
430-
**📊 Matriz de seguridad:**
431-
432-
```
433-
Más seguro ───────────────────────────────── Menos seguro
434-
↓ ↓
435-
[Por defecto] → [no-new-privileges] → [seccomp=unconfined] → [--privileged]
436-
(seguro) (muy seguro) (arriesgado) (muy arriesgado)
437-
```
438-
439-
### 🧠 **Memoria compartida (--shm-size)**
440-
441-
Algunos navegadores y apps gráficas necesitan más memoria compartida:
442-
443-
```bash
444-
--shm-size="1gb" # Asigna 1GB de memoria compartida
445-
--shm-size="512m" # Asigna 512MB
446-
```
447-
448-
**🎯 Uso típico**: Firefox, Chrome, aplicaciones que renderizan gráficos.
449-
450-
### 🎭 **Privilegios (--privileged)**
451-
452-
Da acceso completo al sistema host al contenedor:
453-
454-
```bash
455-
--privileged # Acceso completo (usar con precaución)
456-
```
457-
458-
**🚨 Solo usar cuando sea absolutamente necesario** (ej: Home Assistant para acceso a hardware USB).
459-
460175
---
461176

462177
## 🌟 Algunas imágenes interesantes
@@ -523,10 +238,9 @@ lscr.io/linuxserver/speedtest-tracker:latest
523238
```bash
524239
docker run -d \
525240
--name=filezilla \
526-
--security-opt seccomp=unconfined `# ¡Recuerdas esto! Para apps gráficas` \
527241
-e PUID=1000 -e PGID=1000 -e TZ=Etc/UTC \
528242
-p 3000:3000 -p 3001:3001 \
529-
--restart unless-stopped `# Política de reinicio que aprendiste` \
243+
--restart unless-stopped \
530244
lscr.io/linuxserver/filezilla:latest
531245
```
532246

@@ -548,7 +262,6 @@ docker run -d \
548262
```bash
549263
docker run -d \
550264
--name=libreoffice \
551-
--security-opt seccomp=unconfined `# Para aplicación gráfica` \
552265
-e PUID=1000 -e PGID=1000 -e TZ=Etc/UTC \
553266
-p 3000:3000 -p 3002:3001 \
554267
lscr.io/linuxserver/libreoffice:latest
@@ -561,11 +274,10 @@ docker rm -f libreoffice # Para limpiar después de probar
561274
```bash
562275
docker run -d \
563276
--name=firefox \
564-
--security-opt seccomp=unconfined `# Necesario para el navegador` \
565277
-e PUID=1000 -e PGID=1000 -e TZ=Etc/UTC \
566-
-e FIREFOX_CLI=https://www.lemoncode.net/ `# URL inicial personalizada` \
278+
-e FIREFOX_CLI=https://www.lemoncode.net/ \
567279
-p 3000:3000 -p 3001:3001 \
568-
--shm-size="1gb" `# ¡Memoria compartida para el navegador!` \
280+
--shm-size="1gb" \
569281
lscr.io/linuxserver/firefox:latest
570282
```
571283

@@ -602,8 +314,6 @@ docker run -d \
602314

603315
**Acceso:** Una vez ejecutado, accede a `http://localhost:5678` para completar la configuración inicial.
604316

605-
> 💡 **Nota**: En próximas clases aprenderemos a usar volúmenes (`-v`) para persistir datos en n8n y otras aplicaciones.
606-
607317
### 📌 ¿Qué puerto tengo que abrir?
608318
¿Y cómo sé qué puertos tengo que abrir? Pues en la documentación de cada imagen te lo indican. Por ejemplo, en la de [Radarr](https://hub.docker.com/r/linuxserver/radarr) te indican que tienes que abrir el puerto 7878.
609319
Por otro lado, puedes saber qué puerto puedes exponer para una imagen que ya tienes descargada con el siguiente comando:

0 commit comments

Comments
 (0)