Blog

Praktyczna lista kontrolna bezpieczeństwa izolacji Dockera dla hostingu wielodostępnego

Zabezpiecz swój wielodostępny hosting Docker za pomocą tej praktycznej listy kontrolnej obejmującej użytkowników niebędących rootem, możliwości, seccomp, przestrzenie nazw użytkowników, limity zasobów i systemy plików tylko do odczytu.

Podsumowanie

Hosting wielodostępny Docker wymaga silnej izolacji, aby zapobiec ucieczkom z kontenerów. Ten artykuł zawiera praktyczną listę kontrolną bezpieczeństwa obejmującą sześć kluczowych obszarów: uruchamianie jako nie-root, usuwanie możliwości, stosowanie profili seccomp, włączanie mapowania przestrzeni nazw użytkowników, ustawianie limitów zasobów i używanie systemów plików tylko do odczytu. Każdy krok zawiera konkretny przykład konfiguracji dla Docker Compose. Dowiesz się również o typowych pułapkach, takich jak problemy ze zgodnością jądra z przestrzeniami nazw użytkowników i kompromisy wydajnościowe przy stosowaniu seccomp. Postępując zgodnie z tą listą kontrolną, możesz znacznie zmniejszyć powierzchnię ataku bez dodawania niepotrzebnej złożoności. Artykuł kończy się zalecaną konfiguracją bazową dla produkcyjnych środowisk wielodostępnych.

Jeśli prowadzisz wielodostępne środowisko Docker, widmo ataku ucieczki z kontenera nie daje Ci spać w nocy. Jeden exploit jądra może wydostać się z kontenera i dać atakującemu nieograniczony dostęp do hosta i danych wszystkich innych dzierżawców. Chociaż Docker zapewnia potężne prymitywy izolacji — przestrzenie nazw, cgroups i możliwości — błędna konfiguracja pozostawia luki. Ten artykuł przedstawia krok po kroku listę kontrolną bezpieczeństwa, którą możesz zastosować już dziś. Każdy krok zawiera działający fragment Docker Compose i kluczowe zastrzeżenia. Na koniec będziesz mieć utwardzoną bazę, która równoważy bezpieczeństwo i wydajność.

1. Uruchamianie kontenerów jako użytkownik niebędący rootem

Kontenery domyślnie działają jako root wewnątrz kontenera. Jeśli atakujący zdobędzie root w kontenerze, ma przewagę w ucieczce. Zawsze definiuj użytkownika niebędącego rootem w swoim Dockerfile.

FROM alpine:3.18
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

W Compose możesz również ustawić użytkownika bezpośrednio:

services:
  app:
    image: myapp
    user: "1000:1000"

Zastrzeżenie: Niektóre aplikacje wymagają roota do legalnych operacji (np. wiązania portów poniżej 1024). Użyj CAP_NET_BIND_SERVICE zamiast uruchamiania całego kontenera jako root. Aby uzyskać głębsze spojrzenie na podstawy izolacji, zobacz nasz przewodnik na temat osiągnięcia prawdziwej izolacji wielodostępnej w Dockerze.

2. Usuń wszystkie możliwości i dodaj tylko to, co jest potrzebne

Możliwości Linuksa dają kontenerom szczegółowe uprawnienia. Domyślnie Docker przyznaje zestaw możliwości. Usuń wszystko i przyznaj tylko te wymagane.

services:
  app:
    image: myapp
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE  # if needed

Zastrzeżenie: Możliwości takie jak SYS_ADMIN lub NET_RAW są rzadko potrzebne. Przejrzyj swoją aplikację, aby określić minimalny zestaw. Usunięcie wszystkich możliwości blokuje wiele wektorów ucieczki.

3. Zastosuj profil Seccomp

Seccomp (tryb bezpiecznego przetwarzania) filtruje wywołania systemowe dostępne dla kontenera. Docker jest wyposażony w domyślny profil seccomp, który blokuje niebezpieczne wywołania systemowe, takie jak clone z pewnymi flagami. Możesz go dodatkowo dostosować.

services:
  app:
    image: myapp
    security_opt:
      - seccomp=/path/to/custom-profile.json

Utwardzony profil może blokować unshare, ptrace i mount. Zacznij od domyślnego profilu Dockera i ogranicz więcej. Zastrzeżenie: Zbyt restrykcyjne profile mogą zepsuć aplikacje. Dokładnie przetestuj w środowisku staging. Więcej na temat obrony przed ucieczką z kontenera przeczytasz w artykule obrona przed ucieczką z kontenera.

4. Włącz mapowanie przestrzeni nazw użytkowników

Przestrzenie nazw użytkowników mapują roota kontenera na nieuprzywilejowanego użytkownika hosta. Oznacza to, że nawet jeśli atakujący zdobędzie root wewnątrz kontenera, nie ma żadnych specjalnych uprawnień na hoście.

Włącz to na demonie Dockera, edytując /etc/docker/daemon.json:

{
  "userns-remap": "default"
}

Następnie uruchom ponownie Docker. Zastrzeżenie: Mapowanie przestrzeni nazw użytkowników ma dwie wady: psuje montowanie woluminów, gdy nie jest starannie skonfigurowane (pliki są własnością mapowanego użytkownika) i jest niezgodne z niektórymi sterownikami przechowywania, takimi jak overlay2 na starszych jądrach. Dokładnie przetestuj.

5. Ustaw limity zasobów za pomocą Cgroups

Limity zasobów zapobiegają przeprowadzeniu ataku typu odmowa usługi przez skompromitowany kontener na hoście. Użyj cgroups, aby ograniczyć CPU, pamięć i wejście/wyjście dysku.

services:
  app:
    image: myapp
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

W przypadku Docker Compose v3 użyj sekcji deploy (działa z swarm lub compose v2). W przypadku czystego Dockera użyj --memory i --cpus. Zastrzeżenie: Ustawienie zbyt niskich limitów może spowodować zabicia OOM. Monitoruj użycie i dostosuj odpowiednio.

6. Użyj systemu plików root tylko do odczytu

System plików root tylko do odczytu uniemożliwia atakującym zapisywanie złośliwych plików binarnych lub modyfikowanie plików konfiguracyjnych wewnątrz kontenera.

services:
  app:
    image: myapp
    read_only: true
    tmpfs:
      - /tmp:noexec,nosuid,size=64m

Zamontuj tmpfs na katalogach wymagających dostępu do zapisu (np. /tmp). To wymusza, aby wszystkie dane do zapisu były efemeryczne. Zastrzeżenie: Niektóre aplikacje wymagają trwałego przechowywania; użyj do tego nazwanych woluminów.

Typowe pułapki

  • Zgodność jądra: Mapowanie przestrzeni nazw użytkowników i niektóre reguły seccomp wymagają nowoczesnego jądra Linuksa (4.14+). Sprawdź wersję swojego jądra.
  • Wpływ na wydajność: Seccomp i przestrzenie nazw użytkowników dodają niewielki narzut, ale jest on pomijalny dla większości obciążeń. Przetestuj swoją konkretną aplikację.
  • Złożoność: Dodanie wszystkich sześciu środków naraz może coś zepsuć. Stosuj je jeden po drugim, testuj każdą zmianę.

Aby uzyskać szerszy obraz wzorców orkiestracji, zobacz nasz przewodnik na temat projektowania wielodostępnej architektury Docker.

Podsumowanie

Bezpieczny wielodostępny host Docker nie wymaga egzotycznych narzędzi — tylko poprawnego użycia wbudowanych funkcji Dockera. Zacznij od użytkownika niebędącego rootem, usuń wszystkie możliwości, zastosuj profil seccomp, włącz mapowanie przestrzeni nazw użytkowników, ustaw limity zasobów i użyj systemu plików tylko do odczytu. Ta lista kontrolna stanowi solidną podstawę, która blokuje najczęstsze techniki ucieczki. Po wdrożeniu uruchom narzędzia bezpieczeństwa, takie jak docker-bench-security, aby zweryfikować konfigurację. Pamiętaj: bezpieczeństwo to proces, a nie produkt. W miarę pojawiania się nowych podatności jądra, przeglądaj swoje ustawienia. Aby uzyskać zautomatyzowane strony docelowe prezentujące Twoją usługę hostingową, użyj Pagenza, aby uruchomić swoją witrynę w minutach.

Sources (5)