Blog

Härtung von Docker-Containern für Multi-Tenant-Hosting: Eine Schritt-für-Schritt-Isolationsanleitung

Erfahren Sie, wie Sie Docker-Container für Multi-Tenant-Umgebungen mit praktischen Sicherheitsmaßnahmen wie Nicht-Root-Benutzern, entfernten Capabilities, schreibgeschützten Dateisystemen und Netzwerkisolation absichern.

Zusammenfassung

Der Betrieb einer Multi-Tenant-Docker-Hosting-Plattform erfordert eine luftdichte Container-Isolation, um zu verhindern, dass sich Mandanten gegenseitig beeinträchtigen oder auf den Host entkommen. Dieser Leitfaden bietet einen konkreten, schrittweisen Härtungsprozess, den Sie heute anwenden können. Sie lernen, Nicht-Root-Benutzer zu konfigurieren, unnötige Linux-Capabilities zu entfernen, Dateisysteme schreibgeschützt zu mounten, Ressourcengrenzen über cgroups durchzusetzen, Netzwerke zu segmentieren und Seccomp- oder AppArmor-Profile anzuwenden. Wir behandeln auch, wann Container mit virtuellen Maschinen für maximale Sicherheit ergänzt werden sollten. Am Ende haben Sie eine Checkliste, um gängige Container-Escape-Vektoren systematisch zu beseitigen und Ihre Multi-Tenant-Infrastruktur wirklich isoliert zu halten.

Das reale Problem mit Multi-Tenant-Containern

Docker-Container teilen sich den Host-Kernel, und wenn die Isolation falsch konfiguriert ist, kann ein Mandant theoretisch auf die Daten eines anderen zugreifen, die gesamte CPU verbrauchen oder sogar auf den Host ausbrechen. Als Hosting-Anbieter benötigen Sie luftdichte Grenzen, ohne die Leistungsvorteile von Containern zu opfern. Viele Teams beginnen mit den Standard-Docker-Einstellungen, die für die Entwicklung und nicht für die Multi-Tenant-Produktion ausgelegt sind. Die gute Nachricht: Mit einer systematischen Härtungs-Checkliste können Sie jeden Container auf ein fast VM-ähnliches Isolationsniveau bringen, während Sie die Geschwindigkeit von Docker beibehalten.

Dieser Artikel führt Sie durch jeden Härtungsschritt mit praktischen Beispielen und Einschränkungen. Am Ende haben Sie einen wiederholbaren Prozess, um sichere Multi-Tenant-Container bereitzustellen.

Schritt 1: Container als Nicht-Root-Benutzer ausführen

Standardmäßig laufen Docker-Container als root. Wenn ein Container kompromittiert wird, erlangt der Angreifer root-Rechte im Container und kann einen Container-Escape versuchen. Erstellen Sie zuerst einen dedizierten Benutzer in Ihrem Dockerfile und wechseln Sie zu diesem:

FROM ubuntu:22.04
RUN useradd -m appuser
USER appuser

Einschränkung: Einige Prozesse (z. B. Binden an Ports < 1024) benötigen root. Verwenden Sie in diesen Fällen das Flag --cap-add, um nur die erforderliche Capability zu gewähren, wie --cap-add=NET_BIND_SERVICE, und führen Sie den Prozess weiterhin unter einem Nicht-Root-Benutzer aus.

Weitere Informationen zur grundlegenden Isolation finden Sie in unserem Leitfaden zur Erreichung echter Multi-Tenant-Isolation in Docker.

Schritt 2: Alle Linux-Capabilities entfernen und nur das Nötige hinzufügen

Linux-Capabilities unterteilen root-Rechte in kleine Einheiten. Docker-Container werden mit einem Standardsatz von Capabilities ausgeliefert, der für Multi-Tenant-Hosting zu permissiv ist. Entfernen Sie alle und fügen Sie nur die hinzu, die Ihre Anwendung benötigt:

docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE my-app

Häufig zu vermeidende Capabilities: SYS_ADMIN (Container-Escape), NET_RAW (Paket-Sniffing), SYS_PTRACE (Prozess-Debugging). Verwenden Sie docker run mit --security-opt no-new-privileges, um Privilegieneskalation über setuid-Binärdateien zu verhindern.

Schritt 3: Root-Dateisystem schreibgeschützt mounten

Angreifer schreiben oft bösartige Skripte in das Container-Dateisystem. Indem Sie das Root-Dateisystem schreibgeschützt machen, verhindern Sie dies:

docker run --read-only --tmpfs /tmp:rw,noexec,nosuid,size=64m my-app

--tmpfs erstellt einen temporären beschreibbaren Mount für Verzeichnisse wie /tmp und /var/run. Das Flag noexec verhindert die Ausführung von diesem Mount. Dieser Ansatz zwingt Angreifer, über beschreibbare Verzeichnisse zu pivotieren, die Sie überwachen können.

Schritt 4: Ressourcengrenzen mit cgroups durchsetzen

Unbegrenzte Container können Denial-of-Service-Angriffe durchführen, indem sie den Host-Speicher oder die CPU erschöpfen. Verwenden Sie die Laufzeitbeschränkungen von Docker:

docker run --memory=512m --memory-swap=512m --cpus=0.5 --pids-limit=100 my-app
  • --memory und --memory-swap setzen harte Grenzen (kein Swap).
  • --cpus begrenzt die CPU.
  • --pids-limit verhindert Fork-Bomben, indem die Anzahl der Prozesse begrenzt wird.

Einschränkung: Ressourcengrenzen werden von cgroups durchgesetzt, verhindern jedoch keine Datenexfiltration über das Netzwerk. Kombinieren Sie dies mit Netzwerkisolation (nächster Schritt).

Schritt 5: Netzwerke mit benutzerdefinierten Docker-Netzwerken segmentieren

Standardmäßig teilen sich Docker-Container ein Bridge-Netzwerk. In einem Multi-Tenant-Setup müssen Sie den Netzwerk-Stack jedes Mandanten isolieren. Erstellen Sie ein dediziertes Netzwerk pro Mandant:

docker network create tenant-alpha --internal
docker run --network tenant-alpha my-app

Verwenden Sie das Flag --internal, um den ausgehenden Internetzugriff zu blockieren, und legen Sie nur notwendige Ports über -p frei. Für fortgeschrittene Netzwerksegmentierung ziehen Sie in Betracht, Web-Apps mit Docker-Isolation zu sichern.

Einschränkung: Interne Netzwerke verhindern die direkte Container-zu-Container-Kommunikation über Mandanten hinweg, aber DNS-Lecks können dennoch auftreten, wenn Sie Host-Networking verwenden. Bleiben Sie bei Bridge- oder Overlay-Netzwerken.

Schritt 6: Seccomp- und AppArmor-Profile anwenden

Seccomp filtert Systemaufrufe, und AppArmor (oder SELinux) erzwingt obligatorische Zugriffskontrollen. Docker bietet ein Standard-Seccomp-Profil, das gefährliche Syscalls wie clone mit bestimmten Flags blockiert. Für eine strengere Isolation erstellen Sie ein benutzerdefiniertes Profil:

docker run --security-opt seccomp=./custom.json --security-opt apparmor=docker-default my-app

Sie können ein Basisprofil mit docker run --rm -it --security-opt seccomp=unconfined my-app strace -c -S time generieren und dann reduzieren. Einschränkung: Zu restriktive Profile können legitime Funktionen beeinträchtigen. Testen Sie gründlich im Staging.

Schritt 7: Hybride Isolation mit virtuellen Maschinen in Betracht ziehen

Wenn Ihre Mandanten absolute Isolation benötigen (z. B. regulierte Branchen), führen Sie Container in einer leichten VM aus. Tools wie Sysbox oder Kata Containers bieten Hardware-Level-Trennung, ohne die Containergeschwindigkeit zu opfern. Dies ist der Ansatz, den Dockers Enhanced Container Isolation (ECI) verwendet. Der Overhead ist zwar höher als bei reinen Containern, aber weitaus geringer als bei vollständigen VMs pro Workload.

Weitere Informationen zur Auswahl des richtigen Isolationsniveaus finden Sie im Artikel Design einer Multi-Tenant-Docker-Architektur.

Alles zusammenfassen: Eine Härtungs-Checkliste

  1. Container mit Nicht-Root-Benutzer erstellen.
  2. Alle Capabilities entfernen, nur erforderliche hinzufügen.
  3. Dateisystem schreibgeschützt mounten mit temporären beschreibbaren Mounts.
  4. Speicher-, CPU- und PID-Grenzen setzen.
  5. Isolierte Docker-Netzwerke pro Mandant erstellen.
  6. Benutzerdefinierte Seccomp- und AppArmor-Profile anwenden.
  7. Hybride VM-Container für hohe Sicherheitsanforderungen evaluieren.

Fazit

Container-Härtung ist keine einmalige Aufgabe – es ist eine fortlaufende Disziplin. Die obigen Schritte bilden eine Sicherheitsbasis für Multi-Tenant-Hosting. Denken Sie daran, dass keine einzelne Maßnahme Sicherheit garantiert; Verteidigung in der Tiefe ist der Schlüssel. Beginnen Sie mit den Grundlagen: Nicht-Root-Benutzer und entfernte Capabilities. Fügen Sie dann Ressourcengrenzen und Netzwerksegmentierung hinzu. Für die sensibelsten Workloads kombinieren Sie Container mit VMs. Mit diesem Leitfaden können Sie sicher Multi-Tenant-Docker-Umgebungen bereitstellen, die sowohl effizient als auch sicher sind.

Sources (5)