Docker Overlay Verschlüsselung

Docker Swarm mit verschlüsseltem Node-to-Node Traffic

VSHNeer Elia hat einen Docker Swarm Cluster mit vollständiger Trafficverschlüsselung innerhalb des Clusters eingerichtet (Crosspost zu seinem privaten Blog):

Ich habe einen Docker Swarm Cluster in der neuen Hetzner Cloud eingerichtet. Das Wichtigste zuerst – die Hetzner Cloud ist wirklich grossartig: Super einfach, super günstig und funktioniert wie erwartet. Es ist kein aufgeblähter Cloud-Anbieter, der über 100 Dienste und Funktionen verfügt, die du für deine Server nutzen kannst. Das hält die Kosten und die Komplexität niedrig – ich bin wirklich ein grosser Fan davon.

Zum eigentlichen Thema: Da das Feature-Set einfach gehalten ist, bietet die Hetzner Cloud (vorerst) kein privates Netzwerk. Bei nur öffentlichen IP-Adressen müssen wir den Overlay-Traffic zwischen unseren Docker-Containern sichern!

Das Problem

Standardmässig verschlüsselt Docker Swarm den Datenverkehr zwischen den Managern, so dass wir dort keine Probleme haben. Diese Standardeinstellung ist jedoch nicht für den Container-zu-Container-Verkehr festgelegt. Jeglicher Datenverkehr, der das Overlay-Netzwerk verwendet, ist standardmässig nicht verschlüsselt, da die meisten Nutzer private Netzwerk-Setups mit einer Floating-IP als Zugriffspunkt auf den Cluster nutzen. Docker geht davon aus, dass das private Netzwerk sicher ist und schont daher einige Ressourcen für andere Aufgaben (was bei DigitalOcean beispielsweise nicht der Fall ist, daher empfehle ich ohnehin die Verwendung der Overlay Verschlüsselung!).

Nehmen wir an, wir haben den folgenden Stack:

version: '3'

services: 
  db: 
    networks: 
      - internal
    image: mysql:5.7
    environment: 
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: securepw

  wordpress: 
    networks: 
      - traefik_public
      - internal
    depends_on: 
      - db
    image: wordpress:latest
    environment: 
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: securepw
    deploy: 
      labels: 
        - traefik.frontend.rule=Host:blog.example.com
        - traefik.docker.network=traefik_public
        - traefik.port=80

networks: 
  traefik_public: 
    external: true
  internal: 

 

Das ist ein WordPress-Stack, das die WP-Seite und eine MySQL-Datenbank erstellt. Diese zwei Netzwerke sind wie folgt definiert:

  • intern
  • traefik_public

Das interne Overlay-Netzwerk wird für die Kommunikation zwischen dem WP-Container und der Datenbank verwendet. Dieses Netzwerk ist von aussen nicht erreichbar. traefik_public ist das Netzwerk, das für den Reverse-Proxy verwendet wird. Es wird nur an den WP-Container angehängt, da dies die einzige öffentlich zugängliche Seite dieses Setups ist.
Das Problem hier ist: Ohne ein gesichertes privates Netzwerk wird der Verkehr, der durch das interne Netzwerk läuft, an einen anderen Worker (Docker-Node) weitergeleitet, und das vollständig offen. Jedes Passwort / Authentifizierung / <SENSITIVE_DATA> wird im Klartext zwischen den Docker Containern gesendet, sofern sie sich auf zwei unterschiedlichen Nodes befinden.

Die meisten Docker-Images sind in ihrer einfachen Verwendung nicht für den öffentlichen Zugriff gedacht und deshalb halten sie die meisten so einfach wie möglich, ohne komplizierte Verschlüsselung. Du kannst aber auch ein eigenes Image erstellen, um die Applikationsseitige Verschlüsselung zu aktivieren.

Die Lösung

Docker hat eine Lösung für dieses Problem. Die Verschlüsselung des Overlay-Netzwerks kann einfach aktiviert werden. Leider habe ich zu diesem Thema nicht viel finden können, weshalb ich dachte, dass ein Blogbeitrag zu diesem speziellen Thema nützlich sein könnte.

Die Verschlüsselung des Netzwerks muss während der Erstellung erfolgen. Ein Netzwerk kann nicht mehr verschlüsselt werden, nachdem es bereits eingerichtet wurde. Um die Verschlüsselung zu aktivieren, müssen wir der Netzwerkdefinition ein Flag hinzufügen:

networks:
   traefik_public:
     external: true
   internal:
     driver_opts:
       encrypted: ""

Das Netzwerk traefik_public ist natürlich auch verschlüsselt, da du das Reverse-Proxying natürlich auch nicht im Klartext willst.

Die Option encrypted erstellt einen IPSec-Tunnel zwischen allen Worker, für die Aufgaben für einen Stack geplant sind. Dadurch wird der gesamte Traffic des Overlay-Netzwerks intern verschlüsselt und ermöglicht so den Datenaustausch sensitiver Daten zwischen der Datenbank und WordPress.

Du kannst die offizielle Dokumentation von Docker zu diesem Thema hier nachlesen.

Abschliessende Gedanken

Die Informationen in Bezug auf die Verschlüsselung sind sehr „versteckt“ und werden meiner Meinung nach meistens ignoriert. Die Leute möchten einfach Anwendungen mit Docker deployen, ohne sich über die darunter liegende Infrastruktur Gedanken machen zu müssen und stossen so auf das Problem wie bspw. Plain-Text Traffic in Overlay-Netzwerken.

Ich hoffe, mit diesem Blog-Post mehr auf Verschlüsselung aufmerksam machen zu können.

Wenn du Fragen dazu hast, lass es mich gerne weiter unten wissen!