Webserver, Reverse Proxy und Container – wie die Schichten zusammenspielen

Aus Tuxipedia

Webserver, Reverse Proxy und Container – wie die Schichten zusammenspielen

Dieser Artikel erklärt die grundlegenden Konzepte hinter einem modernen Web-Setup: Was macht eigentlich welche Schicht? Und warum müssen alle zusammenpassen?

Das Prinzip gilt unabhängig davon ob die Dienste in Docker-Containern laufen oder direkt auf einem Server ("bare metal") installiert sind.


Das Grundprinzip: Schichten

Ein modernes Web-Setup besteht aus mehreren unabhängigen Schichten, die jeweils eine eigene Aufgabe haben:

Schicht Aufgabe Beispiel
Netzwerk Wer darf mit wem reden? Docker-Netzwerk / Firewall
Reverse Proxy Wer bekommt welche Anfrage? Caddy / nginx
Anwendung Was wird verarbeitet? Nextcloud / Collabora
Browser Was wird angezeigt? Chrome / Firefox

Jede Schicht schützt und kontrolliert – unabhängig von den anderen. Fällt eine Schicht aus oder wird umgangen, stehen die anderen noch. Dieses Prinzip heißt Defense in Depth.


"Bare Metal" vs. Docker – derselbe Gedanke, andere Werkzeuge

Ob ein Dienst direkt auf dem Server läuft ("Bare Metal") oder in einem Container: Die Konzepte sind identisch. Nur die Werkzeuge unterscheiden sich.

Konzept "Bare Metal" Docker
Dienst starten systemd / init.d docker compose up
Netzwerk trennen Firewall (iptables, ufw) Docker-Netzwerk
Dienste verbinden localhost / IP-Adresse Container-Name
Reverse Proxy nginx / Caddy direkt installiert Caddy als Container
Konfiguration Dateien in /etc/ docker-compose.yml + Caddyfile

Konkret: Ob Nextcloud auf Port 8080 unter localhost:8080 läuft oder als Container namens nextcloud – Caddy spricht in beiden Fällen dieselbe Sprache. Nur die Adresse ändert sich.


Die drei Schutzschichten vor einem Dienst

Am Beispiel von Collabora (dem Office-Server hinter Nextcloud) lässt sich gut zeigen wie die Schichten zusammenwirken.

Schicht 1: Das Netzwerk

Wo: docker-compose.yml, Abschnitt networks

networks:
  tuxi_network:
    external: true

Und beim Collabora-Container:

collabora:
  networks: [tuxi_network]
  # keine "ports:" → kein direkter Zugriff von außen!

Was es bewirkt: Collabora ist nur innerhalb des Docker-Netzwerks erreichbar. Von außen – also vom Internet – gibt es keinen direkten Weg zum Dienst. Nur Caddy, der ebenfalls im selben Netzwerk sitzt, kann Collabora ansprechen.

Auf bare metal entspricht das einer Firewall-Regel: iptables -A INPUT -p tcp --dport 9980 -j DROP – Port 9980 von außen gesperrt, nur lokale Verbindungen erlaubt.

Schicht 2: Die Pfad-Whitelist im Reverse Proxy

Wo: Caddyfile, Block collabora.tuxi.ddnss.de

@allowed path /browser/* /hosting/capabilities /hosting/discovery /cool/* /lool/*
handle @allowed {
    reverse_proxy collabora:9980
}
handle {
    respond 403
}

Was es bewirkt: Caddy lässt nur definierte Pfade durch. Alles andere – auch wenn jemand den Dienst erreichen könnte – bekommt sofort eine 403-Antwort, ohne dass Collabora überhaupt kontaktiert wird.

Collabora hat viele interne Pfade die nie für die Außenwelt gedacht waren. Die Whitelist sorgt dafür dass nur die fünf benötigten Pfade erreichbar sind.

Auf bare metal: dieselbe nginx-Konfiguration, dieselbe Logik – nur andere Syntax.

Schicht 3: Die Anwendungs-Allowlist (aliasgroup)

Wo: docker-compose.yml, Umgebungsvariablen des Collabora-Containers

environment:
  - aliasgroup1=https://cirruscloud.tuxi.ddnss.de
  - domain=^nextcloud$|^cirruscloud\.tuxi\.ddnss\.de(:443)?$

Was es bewirkt: Das ist eine interne Collabora-Einstellung – unabhängig von Caddy. Collabora selbst prüft bei jedem Dokument-Aufruf: Kommt dieser WOPI-Request von einer erlaubten Quelle?

Nur Nextcloud (cirruscloud.tuxi.ddnss.de) darf Dokumente öffnen. Ein Bot der es durch Caddy schafft würde an dieser Stelle scheitern – Collabora würde das Dokument schlicht nicht öffnen.

Auf bare metal: dieselbe Einstellung in /etc/coolwsd/coolwsd.xml unter <storage><wopi><host>.


Das Zusammenspiel: Wer spricht mit wem?

Internet
    │
    ▼
[Caddy] ──────────────────────── einziger Eintrittspunkt
    │                            prüft: Pfad erlaubt?
    │                            setzt: Security-Header
    │
    ▼
[Collabora] ◄──────────────────── nur aus dem Docker-Netz erreichbar
    │                            prüft: kommt der Request von Nextcloud?
    │
    ▼
[Nextcloud] ◄──────────────────── speichert / liefert Dokumente

Der Browser des Nutzers spricht nur mit Caddy. Caddy spricht mit Collabora und Nextcloud. Collabora spricht mit Nextcloud (WOPI). Nextcloud spricht mit der Datenbank.

Keiner dieser internen Dienste ist direkt vom Internet erreichbar.


Die Security-Header: Was der Browser wissen muss

Wo: Caddyfile, header-Block in jedem Domain-Abschnitt

header {
    -Server
    Strict-Transport-Security "max-age=31536000"
    X-Content-Type-Options "nosniff"
    X-Frame-Options "SAMEORIGIN"
    Referrer-Policy "no-referrer"
}

Diese Header schützen nicht den Server – sie schützen den Browser des Nutzers. Sie sagen dem Browser wie er mit den Antworten umgehen soll.

Auf bare metal: exakt dieselben Header, nur in der nginx/Apache-Konfiguration gesetzt. Das Konzept ist HTTP-Standard – unabhängig von der Software.

Für eine detaillierte Erklärung der einzelnen Header: → Caddy – Konzepte und Konfiguration#header


Warum muss das alles zusammenpassen?

Compose und Caddyfile sprechen verschiedene Sprachen – aber sie müssen denselben Namen für einen Dienst verwenden:

# docker-compose.yml
container_name: collabora
# Caddyfile
reverse_proxy collabora:9980

Docker's internes DNS löst collabora automatisch zur richtigen IP-Adresse auf. Das ist die unsichtbare Brücke zwischen beiden Dateien.

Auf bare metal gibt es kein Docker-DNS – dort steht dann localhost:9980 oder eine feste IP. Das Prinzip ist dasselbe, die Adresse ist eine andere.


Zusammenfassung

Was Wo konfiguriert Schützt gegen
Kein direkter Port docker-compose.yml (ports: weggelassen) Direktzugriff aus dem Internet
Pfad-Whitelist Caddyfile (@allowed) Zugriff auf interne Dienst-Pfade
aliasgroup docker-compose.yml (Umgebungsvariable) Fremde WOPI-Clients
Security-Header Caddyfile (header) Browser-seitige Angriffe
Docker-Netzwerk docker-compose.yml (networks:) Kommunikation zwischen unbekannten Containern

Jede Zeile ist unabhängig. Alle zusammen bilden die Festung. 🏰


Siehe auch